From 2144a9084cad74d63d7a0708b079e95b3d2dfb53 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Wed, 26 Sep 2018 17:28:01 +0100 Subject: [PATCH] Fixes by Cheeseh and Ducky --- README.md | 18 +- linux_sdk/Makefile.HPB_bot2_DebugWin32 | 2 +- linux_sdk/Makefile.HPB_bot2_ReleaseWin32 | 2 +- ...kefile.HPB_bot2_Release_NonHomeFolderWin32 | 2 +- linux_sdk/Makefile.rcbot2 | 10 +- linux_sdk/vcpm | Bin 1310840 -> 330800 bytes tier1/KeyValues.cpp | 2539 +++++++ tier1/NetAdr.cpp | 331 + tier1/bitbuf.cpp | 1269 ++++ tier1/byteswap.cpp | 90 + tier1/characterset.cpp | 41 + tier1/checksum_crc.cpp | 180 + tier1/checksum_md5.cpp | 271 + tier1/commandbuffer.cpp | 636 ++ tier1/convar.cpp | 1241 ++++ tier1/datamanager.cpp | 410 ++ tier1/diff.cpp | 547 ++ tier1/generichash.cpp | 303 + tier1/interface.cpp | 465 ++ tier1/mempool.cpp | 317 + tier1/memstack.cpp | 300 + tier1/newbitbuf.cpp | 713 ++ tier1/processor_detect.cpp | 278 + tier1/processor_detect_linux.cpp | 47 + tier1/rangecheckedvar.cpp | 41 + tier1/stringpool.cpp | 334 + tier1/strtools.cpp | 2015 +++++ tier1/tier1-2005.vcproj | 569 ++ tier1/tier1.cpp | 63 + tier1/tokenreader.cpp | 480 ++ tier1/undiff.cpp | 94 + tier1/uniqueid.cpp | 177 + tier1/utlbuffer.cpp | 1753 +++++ tier1/utlbufferutil.cpp | 561 ++ tier1/utlstring.cpp | 334 + tier1/utlsymbol.cpp | 397 + utils/RCBot2_meta/bot_const.h | 4 +- utils/RCBot2_meta/bot_fortress.cpp | 1 - utils/RCBot2_meta/bot_perceptron.cpp | 4 +- utils/RCBot2_meta/bot_perceptron.h | 2 +- utils/RCBot2_meta/bot_plugin_meta.cpp | 4 +- utils/common/ISQLDBReplyTarget.h | 29 + utils/common/MySqlDatabase.cpp | 192 + utils/common/MySqlDatabase.h | 104 + utils/common/bsplib.cpp | 2456 +++++++ utils/common/bsplib.h | 371 + utils/common/cmdlib.cpp | 948 +++ utils/common/cmdlib.h | 170 + utils/common/consolewnd.cpp | 322 + utils/common/consolewnd.h | 45 + utils/common/filesystem_tools.cpp | 214 + utils/common/filesystem_tools.h | 57 + utils/common/map_shared.cpp | 133 + utils/common/map_shared.h | 91 + utils/common/movie.h | 34 + utils/common/mpi_stats.cpp | 799 ++ utils/common/mpi_stats.h | 59 + utils/common/mstristrip.cpp | 928 +++ utils/common/mstristrip.h | 43 + utils/common/pacifier.cpp | 56 + utils/common/pacifier.h | 22 + utils/common/physdll.cpp | 31 + utils/common/physdll.h | 30 + utils/common/polylib.cpp | 915 +++ utils/common/polylib.h | 78 + utils/common/qfiles.h | 42 + utils/common/scratchpad_helpers.cpp | 103 + utils/common/scratchpad_helpers.h | 25 + utils/common/scriplib.cpp | 670 ++ utils/common/scriplib.h | 57 + utils/common/threads.cpp | 250 + utils/common/threads.h | 56 + utils/common/tools_minidump.cpp | 61 + utils/common/tools_minidump.h | 30 + utils/common/utilmatlib.cpp | 184 + utils/common/utilmatlib.h | 41 + utils/common/vmpi_tools_shared.cpp | 234 + utils/common/vmpi_tools_shared.h | 46 + utils/common/wadlib.c | 334 + utils/common/wadlib.h | 46 + utils/mmsource/.gitignore | 1 - utils/mmsource/AMBuildScript | 370 +- utils/mmsource/configure.py | 24 +- utils/mmsource/core-legacy/AMBuilder | 20 + utils/mmsource/core-legacy/CPlugin.cpp | 721 ++ utils/mmsource/core-legacy/CPlugin.h | 159 + utils/mmsource/core-legacy/CSmmAPI.cpp | 653 ++ utils/mmsource/core-legacy/CSmmAPI.h | 88 + utils/mmsource/core-legacy/IPluginManager.h | 137 + utils/mmsource/core-legacy/ISmmAPI.h | 349 + utils/mmsource/core-legacy/ISmmPlugin.h | 430 ++ utils/mmsource/core-legacy/Makefile | 79 + utils/mmsource/core-legacy/concommands.cpp | 793 ++ utils/mmsource/core-legacy/concommands.h | 44 + utils/mmsource/core-legacy/convar_smm.h | 528 ++ utils/mmsource/core-legacy/gamedll_bridge.cpp | 133 + .../core-legacy/msvc10/mm_core-legacy.sln | 20 + .../core-legacy/msvc10/mm_core-legacy.vcxproj | 170 + .../msvc10/mm_core-legacy.vcxproj.filters | 133 + .../core-legacy/msvc9/mm_core-legacy.sln | 20 + .../core-legacy/msvc9/mm_core-legacy.vcproj | 357 + utils/mmsource/core-legacy/oslink.cpp | 81 + utils/mmsource/core-legacy/oslink.h | 93 + .../core-legacy/sourcehook/FastDelegate.h | 3811 ++++++++++ .../sourcehook/generate/FastDelegate.h | 3811 ++++++++++ .../sourcehook/generate/FastDelegate.hxx | 1054 +++ .../core-legacy/sourcehook/generate/generate | 7 + .../sourcehook/generate/generate.bat | 10 + .../sourcehook/generate/sh_memfuncinfo.h | 912 +++ .../sourcehook/generate/sh_memfuncinfo.hxx | 332 + .../sourcehook/generate/shworker.bin | Bin 0 -> 59291 bytes .../sourcehook/generate/shworker/Makefile | 13 + .../generate/shworker/fd_hopter.cpp | 370 + .../generate/shworker/msvc7/shworker.vcproj | 137 + .../generate/shworker/msvc8/shworker.vcproj | 208 + .../sourcehook/generate/shworker/shworker.cpp | 767 ++ .../sourcehook/generate/sourcehook.h | 6537 ++++++++++++++++ .../sourcehook/generate/sourcehook.hxx | 1503 ++++ .../mmsource/core-legacy/sourcehook/sh_list.h | 291 + .../core-legacy/sourcehook/sh_listcat.h | 147 + .../core-legacy/sourcehook/sh_memfuncinfo.h | 912 +++ .../core-legacy/sourcehook/sh_memory.h | 340 + .../core-legacy/sourcehook/sh_stack.h | 237 + .../core-legacy/sourcehook/sh_string.h | 401 + .../core-legacy/sourcehook/sh_tinyhash.h | 534 ++ .../core-legacy/sourcehook/sh_vector.h | 519 ++ .../core-legacy/sourcehook/sourcehook.cpp | 1463 ++++ .../core-legacy/sourcehook/sourcehook.h | 6547 +++++++++++++++++ .../core-legacy/sourcehook/sourcehook_impl.h | 817 ++ .../core-legacy/sourcehook/test/Makefile | 63 + .../core-legacy/sourcehook/test/main.cpp | 132 + .../sourcehook/test/msvc7/test.vcproj | 374 + .../sourcehook/test/msvc8/test.vcproj | 517 ++ .../sourcehook/test/sourcehook_test.h | 27 + .../core-legacy/sourcehook/test/test1.cpp | 723 ++ .../core-legacy/sourcehook/test/test2.cpp | 172 + .../core-legacy/sourcehook/test/test3.cpp | 232 + .../core-legacy/sourcehook/test/test4.cpp | 425 ++ .../core-legacy/sourcehook/test/testbail.cpp | 115 + .../core-legacy/sourcehook/test/testbail.h | 39 + .../core-legacy/sourcehook/test/testbail2.cpp | 36 + .../core-legacy/sourcehook/test/testevents.h | 161 + .../core-legacy/sourcehook/test/testlist.cpp | 282 + .../sourcehook/test/testmanual.cpp | 369 + .../core-legacy/sourcehook/test/testmulti.cpp | 106 + .../sourcehook/test/testrecall.cpp | 231 + .../sourcehook/test/testreentr.cpp | 609 ++ .../core-legacy/sourcehook/test/testref.cpp | 162 + .../sourcehook/test/testrefret.cpp | 202 + .../sourcehook/test/testvphooks.cpp | 260 + utils/mmsource/core-legacy/sourcemm.cpp | 656 ++ utils/mmsource/core-legacy/sourcemm.h | 119 + utils/mmsource/core-legacy/util.cpp | 340 + utils/mmsource/core-legacy/util.h | 109 + utils/mmsource/core-legacy/version.rc | 102 + utils/mmsource/core-legacy/vsp_bridge.cpp | 138 + utils/mmsource/core/AMBuilder | 53 +- utils/mmsource/core/ISmmAPI.h | 9 +- utils/mmsource/core/ISmmPlugin.h | 12 +- utils/mmsource/core/ISmmPluginExt.h | 2 +- utils/mmsource/core/gamedll_bridge.cpp | 4 - utils/mmsource/core/metamod.cpp | 245 +- utils/mmsource/core/metamod_console.cpp | 162 +- utils/mmsource/core/metamod_oslink.cpp | 2 +- utils/mmsource/core/metamod_oslink.h | 10 +- utils/mmsource/core/metamod_provider.h | 14 - utils/mmsource/core/provider/console.cpp | 2 +- utils/mmsource/core/provider/console.h | 2 +- utils/mmsource/core/provider/provider_ep2.cpp | 230 +- utils/mmsource/core/provider/provider_ep2.h | 13 - utils/mmsource/core/sourcehook/FastDelegate.h | 3061 +++++++- .../core/sourcehook/generate/FastDelegate.hxx | 1054 +++ .../core/sourcehook/generate/generate | 2 + .../core/sourcehook/generate/generate.bat | 4 +- .../sourcehook/generate/sh_memfuncinfo.hxx | 332 + .../core/sourcehook/generate/sourcehook.hxx | 371 +- .../mmsource/core/sourcehook/sh_memfuncinfo.h | 625 +- utils/mmsource/core/sourcehook/sh_memory.h | 20 +- utils/mmsource/core/sourcehook/sourcehook.h | 5347 ++++++++++++-- .../sourcehook/sourcehook_impl_cvfnptr.cpp | 38 +- utils/mmsource/core/sourcehook/test/main.cpp | 25 +- .../core/sourcehook/test/testhookmangen.cpp | 32 +- .../core/sourcehook/test/testoddthunks.cpp | 29 +- .../core/sourcehook/test/testvphooks.cpp | 19 +- utils/mmsource/core/version.rc | 8 +- utils/mmsource/core/vsp_bridge.cpp | 5 +- utils/mmsource/loader/AMBuilder | 18 +- utils/mmsource/loader/gamedll.cpp | 459 +- utils/mmsource/loader/loader.cpp | 80 +- utils/mmsource/loader/loader.h | 2 +- utils/mmsource/loader/utility.cpp | 34 +- utils/mmsource/loader/utility.h | 4 +- utils/mmsource/loader/version.rc | 8 +- utils/mmsource/product.version | 2 +- utils/mmsource/public/metamod_version.h | 32 +- utils/mmsource/pushbuild.txt | 21 +- utils/mmsource/sample_mm/Makefile | 44 +- utils/mmsource/sample_mm/sample_mm.cpp | 1 + utils/mmsource/stub_mm/Makefile | 44 +- utils/mmsource/support/buildbot/PackageScript | 20 +- utils/mmsource/support/buildbot/Versioning | 14 +- utils/mmsource/support/buildbot/bootstrap.pl | 7 - .../support/buildbot/generate_headers.py | 32 +- utils/mmsource/support/buildbot/package.pl | 2 +- utils/mmsource/support/buildbot/startbuild.pl | 6 - utils/mmsource/support/changelog.txt | 92 + utils/mmsource/versionlib/AMBuildScript | 21 +- utils/mmsource/versionlib/versionlib.cpp | 8 +- utils/mmsource/versionlib/versionlib.h | 21 +- utils/vprojtomake/makefilecreator.cpp | 276 + utils/vprojtomake/makefilecreator.h | 63 + utils/vprojtomake/stdafx.cpp | 15 + utils/vprojtomake/stdafx.h | 26 + utils/vprojtomake/tinyxml/tinystr.cpp | 116 + utils/vprojtomake/tinyxml/tinystr.h | 319 + utils/vprojtomake/tinyxml/tinyxml.cpp | 1839 +++++ utils/vprojtomake/tinyxml/tinyxml.h | 1799 +++++ utils/vprojtomake/tinyxml/tinyxmlerror.cpp | 52 + utils/vprojtomake/tinyxml/tinyxmlparser.cpp | 1635 ++++ utils/vprojtomake/vcprojconvert.cpp | 661 ++ utils/vprojtomake/vcprojconvert.h | 118 + utils/vprojtomake/vprojtomake.cpp | 136 + utils/vprojtomake/vprojtomake.sln | 20 + utils/vprojtomake/vprojtomake.vcxproj | 297 + utils/vprojtomake/vprojtomake.vcxproj.filters | 121 + 225 files changed, 88312 insertions(+), 2820 deletions(-) create mode 100644 tier1/KeyValues.cpp create mode 100644 tier1/NetAdr.cpp create mode 100644 tier1/bitbuf.cpp create mode 100644 tier1/byteswap.cpp create mode 100644 tier1/characterset.cpp create mode 100644 tier1/checksum_crc.cpp create mode 100644 tier1/checksum_md5.cpp create mode 100644 tier1/commandbuffer.cpp create mode 100644 tier1/convar.cpp create mode 100644 tier1/datamanager.cpp create mode 100644 tier1/diff.cpp create mode 100644 tier1/generichash.cpp create mode 100644 tier1/interface.cpp create mode 100644 tier1/mempool.cpp create mode 100644 tier1/memstack.cpp create mode 100644 tier1/newbitbuf.cpp create mode 100644 tier1/processor_detect.cpp create mode 100644 tier1/processor_detect_linux.cpp create mode 100644 tier1/rangecheckedvar.cpp create mode 100644 tier1/stringpool.cpp create mode 100644 tier1/strtools.cpp create mode 100644 tier1/tier1-2005.vcproj create mode 100644 tier1/tier1.cpp create mode 100644 tier1/tokenreader.cpp create mode 100644 tier1/undiff.cpp create mode 100644 tier1/uniqueid.cpp create mode 100644 tier1/utlbuffer.cpp create mode 100644 tier1/utlbufferutil.cpp create mode 100644 tier1/utlstring.cpp create mode 100644 tier1/utlsymbol.cpp create mode 100644 utils/common/ISQLDBReplyTarget.h create mode 100644 utils/common/MySqlDatabase.cpp create mode 100644 utils/common/MySqlDatabase.h create mode 100644 utils/common/bsplib.cpp create mode 100644 utils/common/bsplib.h create mode 100644 utils/common/cmdlib.cpp create mode 100644 utils/common/cmdlib.h create mode 100644 utils/common/consolewnd.cpp create mode 100644 utils/common/consolewnd.h create mode 100644 utils/common/filesystem_tools.cpp create mode 100644 utils/common/filesystem_tools.h create mode 100644 utils/common/map_shared.cpp create mode 100644 utils/common/map_shared.h create mode 100644 utils/common/movie.h create mode 100644 utils/common/mpi_stats.cpp create mode 100644 utils/common/mpi_stats.h create mode 100644 utils/common/mstristrip.cpp create mode 100644 utils/common/mstristrip.h create mode 100644 utils/common/pacifier.cpp create mode 100644 utils/common/pacifier.h create mode 100644 utils/common/physdll.cpp create mode 100644 utils/common/physdll.h create mode 100644 utils/common/polylib.cpp create mode 100644 utils/common/polylib.h create mode 100644 utils/common/qfiles.h create mode 100644 utils/common/scratchpad_helpers.cpp create mode 100644 utils/common/scratchpad_helpers.h create mode 100644 utils/common/scriplib.cpp create mode 100644 utils/common/scriplib.h create mode 100644 utils/common/threads.cpp create mode 100644 utils/common/threads.h create mode 100644 utils/common/tools_minidump.cpp create mode 100644 utils/common/tools_minidump.h create mode 100644 utils/common/utilmatlib.cpp create mode 100644 utils/common/utilmatlib.h create mode 100644 utils/common/vmpi_tools_shared.cpp create mode 100644 utils/common/vmpi_tools_shared.h create mode 100644 utils/common/wadlib.c create mode 100644 utils/common/wadlib.h create mode 100644 utils/mmsource/core-legacy/AMBuilder create mode 100644 utils/mmsource/core-legacy/CPlugin.cpp create mode 100644 utils/mmsource/core-legacy/CPlugin.h create mode 100644 utils/mmsource/core-legacy/CSmmAPI.cpp create mode 100644 utils/mmsource/core-legacy/CSmmAPI.h create mode 100644 utils/mmsource/core-legacy/IPluginManager.h create mode 100644 utils/mmsource/core-legacy/ISmmAPI.h create mode 100644 utils/mmsource/core-legacy/ISmmPlugin.h create mode 100644 utils/mmsource/core-legacy/Makefile create mode 100644 utils/mmsource/core-legacy/concommands.cpp create mode 100644 utils/mmsource/core-legacy/concommands.h create mode 100644 utils/mmsource/core-legacy/convar_smm.h create mode 100644 utils/mmsource/core-legacy/gamedll_bridge.cpp create mode 100644 utils/mmsource/core-legacy/msvc10/mm_core-legacy.sln create mode 100644 utils/mmsource/core-legacy/msvc10/mm_core-legacy.vcxproj create mode 100644 utils/mmsource/core-legacy/msvc10/mm_core-legacy.vcxproj.filters create mode 100644 utils/mmsource/core-legacy/msvc9/mm_core-legacy.sln create mode 100644 utils/mmsource/core-legacy/msvc9/mm_core-legacy.vcproj create mode 100644 utils/mmsource/core-legacy/oslink.cpp create mode 100644 utils/mmsource/core-legacy/oslink.h create mode 100644 utils/mmsource/core-legacy/sourcehook/FastDelegate.h create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/FastDelegate.h create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/FastDelegate.hxx create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/generate create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/generate.bat create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/sh_memfuncinfo.h create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/sh_memfuncinfo.hxx create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/shworker.bin create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/shworker/Makefile create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/shworker/fd_hopter.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/shworker/msvc7/shworker.vcproj create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/shworker/msvc8/shworker.vcproj create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/shworker/shworker.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/sourcehook.h create mode 100644 utils/mmsource/core-legacy/sourcehook/generate/sourcehook.hxx create mode 100644 utils/mmsource/core-legacy/sourcehook/sh_list.h create mode 100644 utils/mmsource/core-legacy/sourcehook/sh_listcat.h create mode 100644 utils/mmsource/core-legacy/sourcehook/sh_memfuncinfo.h create mode 100644 utils/mmsource/core-legacy/sourcehook/sh_memory.h create mode 100644 utils/mmsource/core-legacy/sourcehook/sh_stack.h create mode 100644 utils/mmsource/core-legacy/sourcehook/sh_string.h create mode 100644 utils/mmsource/core-legacy/sourcehook/sh_tinyhash.h create mode 100644 utils/mmsource/core-legacy/sourcehook/sh_vector.h create mode 100644 utils/mmsource/core-legacy/sourcehook/sourcehook.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/sourcehook.h create mode 100644 utils/mmsource/core-legacy/sourcehook/sourcehook_impl.h create mode 100644 utils/mmsource/core-legacy/sourcehook/test/Makefile create mode 100644 utils/mmsource/core-legacy/sourcehook/test/main.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/msvc7/test.vcproj create mode 100644 utils/mmsource/core-legacy/sourcehook/test/msvc8/test.vcproj create mode 100644 utils/mmsource/core-legacy/sourcehook/test/sourcehook_test.h create mode 100644 utils/mmsource/core-legacy/sourcehook/test/test1.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/test2.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/test3.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/test4.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/testbail.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/testbail.h create mode 100644 utils/mmsource/core-legacy/sourcehook/test/testbail2.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/testevents.h create mode 100644 utils/mmsource/core-legacy/sourcehook/test/testlist.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/testmanual.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/testmulti.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/testrecall.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/testreentr.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/testref.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/testrefret.cpp create mode 100644 utils/mmsource/core-legacy/sourcehook/test/testvphooks.cpp create mode 100644 utils/mmsource/core-legacy/sourcemm.cpp create mode 100644 utils/mmsource/core-legacy/sourcemm.h create mode 100644 utils/mmsource/core-legacy/util.cpp create mode 100644 utils/mmsource/core-legacy/util.h create mode 100644 utils/mmsource/core-legacy/version.rc create mode 100644 utils/mmsource/core-legacy/vsp_bridge.cpp create mode 100644 utils/mmsource/core/sourcehook/generate/FastDelegate.hxx create mode 100644 utils/mmsource/core/sourcehook/generate/sh_memfuncinfo.hxx create mode 100644 utils/vprojtomake/makefilecreator.cpp create mode 100644 utils/vprojtomake/makefilecreator.h create mode 100644 utils/vprojtomake/stdafx.cpp create mode 100644 utils/vprojtomake/stdafx.h create mode 100644 utils/vprojtomake/tinyxml/tinystr.cpp create mode 100644 utils/vprojtomake/tinyxml/tinystr.h create mode 100644 utils/vprojtomake/tinyxml/tinyxml.cpp create mode 100644 utils/vprojtomake/tinyxml/tinyxml.h create mode 100644 utils/vprojtomake/tinyxml/tinyxmlerror.cpp create mode 100644 utils/vprojtomake/tinyxml/tinyxmlparser.cpp create mode 100644 utils/vprojtomake/vcprojconvert.cpp create mode 100644 utils/vprojtomake/vcprojconvert.h create mode 100644 utils/vprojtomake/vprojtomake.cpp create mode 100644 utils/vprojtomake/vprojtomake.sln create mode 100644 utils/vprojtomake/vprojtomake.vcxproj create mode 100644 utils/vprojtomake/vprojtomake.vcxproj.filters diff --git a/README.md b/README.md index e3afa8a5..b76a628f 100644 --- a/README.md +++ b/README.md @@ -8,21 +8,15 @@ Note that this is mainly intended for TF2. ## Building ### Windows -Make sure to have Visual Studio 2013 installed. -Other than that, it should compile fine, even with the latest Visual Studio 2017. +Make sure you have Visual Studio 2013 installed. +Other than that it should compile fine, even with the latest Visual Studio 2017. ### Linux -Run ./compile.sh in 'linux_sdk' - -Alternatively: * Go to `linux_sdk` -* Type `make -f Makefile.rcbot2 vcpm` -* Type `make -f Makefile.rcbot2 genmf` (this will generate the Makefiles) -* Edit `Makefile.rcbot2` and `Makefile.HPB_bot2_*` according to your needs - * Most of the time you will only need to modify Line 21 and 55 of `Makefile.rcbot2` -* Type `make -f Makefile.rcbot2 all -j4 2> error.log` -* Check the `error.log` - +* `make -f Makefile.rcbot2 vcpm` +* `make -f Makefile.rcbot2 genmf` (this will generate the Makefiles) +* `make -f Makefile.rcbot2 all -j4` +And a `RCBot2Meta_i486.so` should appear in the folder. --- Make sure to check out the [bots-united.com discord](https://discord.gg/BbxR5wY) for support and to stay updated. \ No newline at end of file diff --git a/linux_sdk/Makefile.HPB_bot2_DebugWin32 b/linux_sdk/Makefile.HPB_bot2_DebugWin32 index 1f36615c..b6be4060 100644 --- a/linux_sdk/Makefile.HPB_bot2_DebugWin32 +++ b/linux_sdk/Makefile.HPB_bot2_DebugWin32 @@ -1,5 +1,5 @@ UTILS_RCBOT2_META_SRC_DIR=../utils/RCBot2_meta -UTILS_RCBOT2_META_OBJ_DIR=obj/$(NAME)_$(ARCH)/utils/RCBot2_meta +UTILS_RCBOT2_META_OBJ_DIR=obj/$(NAME)_$(ARCH)/utilsBot2_metmeta INCLUDES=-I../utils/RCBot2_meta/../../public/mathlib -I../utils/RCBot2_meta/../../public -I../utils/RCBot2_meta/../../public/engine -I../utils/RCBot2_meta/../../public/tier0 -I../utils/RCBot2_meta/../../public/tier1 -I../utils/RCBot2_meta/../../dlls -I../utils/RCBot2_meta/../../game_shared -I../utils/RCBot2_meta/../../game/shared -I../utils/RCBot2_meta/../../game/server -I../utils/RCBot2_meta/../../public/game/server -I../utils/RCBot2_meta/../mmsource/public -I../utils/RCBot2_meta/../mmsource/core -I../utils/RCBot2_meta/../mmsource/core/sourcehook -D_DEBUG -DHOMEFOLDER diff --git a/linux_sdk/Makefile.HPB_bot2_ReleaseWin32 b/linux_sdk/Makefile.HPB_bot2_ReleaseWin32 index ac8b9792..8b876487 100644 --- a/linux_sdk/Makefile.HPB_bot2_ReleaseWin32 +++ b/linux_sdk/Makefile.HPB_bot2_ReleaseWin32 @@ -1,5 +1,5 @@ UTILS_RCBOT2_META_SRC_DIR=../utils/RCBot2_meta -UTILS_RCBOT2_META_OBJ_DIR=obj/$(NAME)_$(ARCH)/utils/RCBot2_meta +UTILS_RCBOT2_META_OBJ_DIR=obj/$(NAME)_$(ARCH)/utilsBot2_metmeta INCLUDES=-I../utils/RCBot2_meta/../../public/mathlib -I../utils/RCBot2_meta/../../public -I../utils/RCBot2_meta/../../public/engine -I../utils/RCBot2_meta/../../public/tier0 -I../utils/RCBot2_meta/../../public/tier1 -I../utils/RCBot2_meta/../../dlls -I../utils/RCBot2_meta/../../game_shared -I../utils/RCBot2_meta/../../game/shared -I../utils/RCBot2_meta/../../game/server -I../utils/RCBot2_meta/../../public/game/server -I../utils/RCBot2_meta/../mmsource/public -I../utils/RCBot2_meta/../mmsource/core -I../utils/RCBot2_meta/../mmsource/core/sourcehook -DNDEBUG -DHOMEFOLDER diff --git a/linux_sdk/Makefile.HPB_bot2_Release_NonHomeFolderWin32 b/linux_sdk/Makefile.HPB_bot2_Release_NonHomeFolderWin32 index c4b74c1c..2234ee51 100644 --- a/linux_sdk/Makefile.HPB_bot2_Release_NonHomeFolderWin32 +++ b/linux_sdk/Makefile.HPB_bot2_Release_NonHomeFolderWin32 @@ -1,5 +1,5 @@ UTILS_RCBOT2_META_SRC_DIR=../utils/RCBot2_meta -UTILS_RCBOT2_META_OBJ_DIR=obj/$(NAME)_$(ARCH)/utils/RCBot2_meta +UTILS_RCBOT2_META_OBJ_DIR=obj/$(NAME)_$(ARCH)/utilsBot2_metmeta INCLUDES=-I../utils/RCBot2_meta/../../public/mathlib -I../utils/RCBot2_meta/../../public -I../utils/RCBot2_meta/../../public/engine -I../utils/RCBot2_meta/../../public/tier0 -I../utils/RCBot2_meta/../../public/tier1 -I../utils/RCBot2_meta/../../dlls -I../utils/RCBot2_meta/../../game_shared -I../utils/RCBot2_meta/../../game/shared -I../utils/RCBot2_meta/../../game/server -I../utils/RCBot2_meta/../../public/game/server -I../utils/RCBot2_meta/../mmsource/public -I../utils/RCBot2_meta/../mmsource/core -I../utils/RCBot2_meta/../mmsource/core/sourcehook -DNDEBUG diff --git a/linux_sdk/Makefile.rcbot2 b/linux_sdk/Makefile.rcbot2 index ee2533de..5f8cd6a4 100644 --- a/linux_sdk/Makefile.rcbot2 +++ b/linux_sdk/Makefile.rcbot2 @@ -10,8 +10,8 @@ # the name of the mod binary (_i486.so is appended to the end) #NAME=server #NAME=HPB_bot2_meta -#NAME=RCBot2Meta -NAME=RCBot2MetaDebug +NAME=RCBot2Meta +#NAME=RCBot2MetaDebug # the location of the vcproj that builds the mod #MOD_PROJ=../game/server/server_hl2mp-2005.vcproj @@ -19,8 +19,8 @@ MOD_PROJ=../utils/RCBot2_meta/HPB_Bot2.vcproj # the name of the mod configuration (typically _) #MOD_CONFIG=ServerHL2MP_ReleaseWin32 -#MOD_CONFIG=HPB_bot2_Release_NonHomeFolderWin32 -MOD_CONFIG=HPB_bot2_DebugWin32 +MOD_CONFIG=HPB_bot2_Release_NonHomeFolderWin32 +#MOD_CONFIG=HPB_bot2_DebugWin32 # the directory the base binaries (tier0_i486.so, etc) are located # this should point to your orange box subfolder of where you have srcds installed. @@ -52,7 +52,7 @@ CLINK=/usr/bin/gcc-4.8 OPTFLAGS=-O1 -fomit-frame-pointer -fforce-addr -fthread-jumps -fcrossjumping -foptimize-sibling-calls -fcse-follow-jumps -fcse-skip-blocks -fgcse -fgcse-lm -frerun-cse-after-loop -fcaller-saves -fpeephole2 -fschedule-insns2 -fsched-interblock -fsched-spec -fregmove -fdelete-null-pointer-checks -freorder-blocks -freorder-functions -falign-functions -falign-jumps -falign-loops -falign-labels -ftree-vrp -ftree-pre -finline-functions -funswitch-loops -fgcse-after-reload -funsafe-math-optimizations # put any compiler flags you want passed here -USER_CFLAGS= -std=c++11 -w -D__linux__ -g -D_DEBUG -DDEBUG -DSH_DEBUG# -DTF2_HOOKS +USER_CFLAGS= -std=c++11 -w -D__linux# -g -D_DEBUG -DDEBUG -DSH_DEBUG# -DTF2_HOOKS # Link Libraries #LIBFILES= \ diff --git a/linux_sdk/vcpm b/linux_sdk/vcpm index b973d76133afc18b24c82b05ae62288d88791c64..acd146c5ddc5d7bd03c8ed2c0f8934ff7561ab8e 100644 GIT binary patch delta 127362 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%0Ak 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 aw6HdE?rmGfcJH_UM8}Ctl@DwD$NvYoFZp@^ literal 1310840 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

    ggM+$1R^!DgU3qYew!PBli>K#>C3$@j2HI!4 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%0Ap6}}~~LAM(jA86d$e1*5cbM!}D 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 v0qb}yKmR@f z9u4@~y2HU1~Ph#PmQzs>{ae~ly7xL5lw1255jt(SVf1U`a&^GPoKCh+Lv?0ziezYAQY zKSjTqPk#g+fS+u2`Tq`_c`TogKf#uNaRK^4-|2Dbo52IDFI3aK|9wi|9{XEA2lkih z`*+|~^m*T&@4OW3_UE6GIXUxFq8{^*Y>ebM^k z)t=9T{iXN)zft;w`QFXFp5Hj;Q&rzgW)rv?$osDX=iwJQ(p27C!QLM#``10-j?b*i zKF8JXFTtVz?_a=EL4Q7eJbvGK+;)NU*wgE-{BiIo{xq$Zdf(098=<$;z#8wn!2VKw z-wD>|iZ0<^?YTdd{sr(N^0BAKe+K8_pY7yV`Pm}$@K9`DxCNZ~Tr59+Rv7=vqRanR zU>)sr{c-mBCr;2`x5fUcK5*!d8wR)IZ$%6?@0$S+^sH~#(_f?K@kf~Thx#lj{mxjv z`#g9xn7{uF4()S~DN*p@b=m)N2f)kt!wxw-t^7ee!>!@T(Ve(>RT;!C(!{=ZD6KLqYz{;L1g{;p}p7k}Pwx%_uriMkx{ zqi2$SB(SGEA3VZ*X(PYp%K~@<{t%jN-uEVO=1lb0<1PLmcyS}2edA}n?*tb1fv>JJ z=O?IsPX#Z1w5{Q<8x}@CwB?_Z83Sj~FCOR0zX!a0Ud&(a0}q_Sv8S&8{!IDZrT+MK z3O@v1V14)FecUYbHLxc<9_%kY|8($S^!+z*ulf#x+p+Jz$KgrvXds{70bYGUEH8XW z`O)_;CBNGLd12b~4EOv$gBOX1@ay+rh4ep<`TbtuO|d=c*TErwc{jLHk3vruyZ1eLKktVhjyc=|UgCU^ zcRIY2axx$E{NqWPQPP+HhR^r9^qasP(Bsn_ej7ORiMED5_c8FweSCi1)%PLr>bBV4 za5@FG;}6k%le~2SIFtv=;MKrh`Fg#$xGwvQ^>%!|06r4<2abRjYO(y)d64=N|9Gvd z-w^m51J?oFbVZ7)!z|{|1f0yXxzrgw5;do2; zzS9p;UZ8(o0``~aa{#=01^n|w+n#;k0mj#_=Pw24=`TNCZvr1d-uLtOgWyn}`xJPU z`s|`?)#rQQl|cSF8V?&sV`qtT!~*yzfWg1?cTMu=;QPjkF*6 z@i^+K`V4|Qus`l}`DehR(BC;O|IOglYh(Z2?cfFa_k5Rs3B2?sZ=ZQm<~a1P{7J~C zZhl-SeJt?zT@GFj>Q?}-yeM7|Un7jZ_iFe4_ku(I`x)>m_P!3%)nDHLFWT-|W_lTfvL0PpXUR`(E(hI)8-XsaC-4h1g#H@8BiupLz1D zzfXJ_H||myXM>M0pZ)sL3tm8ext=tYf17Y%FaHvFfcdq-rT+vR%A36}CqMkw`#WC- zJ~Gbn`7ZxE!1o09xQ~Lv_}>SGUm4pQ{sz2oXRNPpcm@4=5yv0WU7a`ur=vOUPq7??vhFRQ~h%gz@nf{}p%y`<(hm^6-Cv7hke2 z``fO(&Rghj_@y7Oo#53id{)e*?*}hkzRv82R{6gLUU_O9zxE;UXs|wi0el4i5NeUB z&v(EB$mfQBdH!*)B>ju)%=twsF9+7~m6|W&2hRhypT%d5Pqxp$9lQWN(2b_NWw5{0 zUta}pfFEeR)ARo*{88xN_3vX5G&c}$cP;69-_yYZf&bz%u)kE^H7R_33f~AGg+FW| zugd#v@Znb@Z}C38|DV7+p=Y46C!TRD{NuG8J?rvc3SOR#<)bn1%B$k|l$U}BSZ^+I z`QHX!4e0G7;Ewy+va6))eNVcL{=%P{bNTzgVSMwo;0?R^M1|{*H-Ym3KY0&$6o2pQ z-ShW>m$t^^|2^T}b=mj1^nV9e1AFVaFv=tF=jSUO{&cDEb7FaS2e>_mAH5IkFZK7g zz~THn?=`d!drTK;>ffutXClw|^=TZOho1Uf`Yqsg=<^8Fj4%7N)-0U*`sU^?Cdef7uAG2J8C{us*--$M^q&mwPy$%G1|tY42rmJbPaFPh)+1 zA9xk{;sm{q_8bN;t`Lvl=;bl5qdmwoKK*InP+#2)KJo$UpV#vRaQpuC**jhRUjkmi zAEf##{cYe;_=otL+VcnCJnN6|um1oKY>Va9$KOu>2lk<7fk%-)&voUE3BwO02CMvA zz$@&(@ciL}U>yyOR zT>5_S0P}g=;WvQ&rSjhn?)XVtcH?90`=87}9C;wNM?MEU%6R(r&VU!OKl}CbH#Km` zA1Crh_5ZZe=ZUvkXX|$o9kCS% zmWO-Q|9o&2`|8sj{vPva8ToI+Np^kPNqXij@&2B7f*0XWdF5xme@N->Qu&_-=ezhM z4fiVlU%(wfyy>>zz_3|loyQmW#A+5PmRCc zHx2%WK>oQ4Jb-_!opkl*N5RYNukh>t7r~>0F+a=vCjI$s^jlZn6Ts)e&!`^j5BeW? zxs%WRxb)`=qmNw*R{ie)x3eCe<}||vrJwv;%opTc^`GkVB=ApO7RQry zDIIy|e)s$y@W3tcdOHJN3HaA5!HZ9i-}iRq|NOe_52>*F82f2dr0T zkyrJ<6}$lbKGoq5fvf-8mi+@qkI#4;cNMps_;cPKxI&%P2ox-(ucC&798+mFXQ z_{inNce&@^4-V~jp9WXIyDs}Q($(M3T!LQNUugI}{AveyIiROG@ak*UWuNNue*qlw z&u@dP0lohl_%QAJR>rpf5q1BX#ed4hx?Uo0Eh9hZw4dKdkPUUsC?UkDEO3(cp}UnRVc z&j7gR{~$;|kKeuyJ`4V?cZuGAsC496@dCXsGc&fYG+CZ573WH0^~&7FVzrtnT)yL~ z&6{=<3bpz1!cd`b-L9x-%TAYZi_N$tH@H7jxNb)j?JpH`h00ucZ+X`IkTXA&XZMdy zmnSm&t8>lMAGb=iHx)zX1&^RvaMLw6&Gs-;3bzrC2*U(}<;%IyBqT-`o<-Htxh zb=TNTsZ}Mrw(QxG=b0_`8B@jWr9*qhrsqpFUqTes3e}OyzS8XG`AJnc#}7NkYV~cD zyrVKUQJ&qqZLTtte!<>Cqo~2TxysydeXO`IQ>)LBzgnqGw{BhUaD8q^saD&)ohA+E z3Yq!(^!WVbWT|CO*9v5(ye(5>bG8w+a>ev&R|mC@f7&!RH+E?4+@0O6a__1P){1c% zs!Hw9%($=mbqsUImaFU2!{*1RV`#QqFEfZQE)DJ(rjge7!oKPMn>eIk?t?CM|w!M?|wW zGxo#NW3{QBV=bmje_>C7%G64t<8pp~xtu9Y6~?BgE5(f!s7ePTs4M<;zE+~MnQT4rZS_=1P0ZwR&l;P@gFjrz^9i8aXB^g}u|2@v-T` z1Wcn=7@I$sDOP5x)1`W8Vq;Hllxv--Fj<~07sf=r1*$uDC^I?7WG+n1&&(X+kpLCQ zSx;mwGW26bszS$_*;bwfOpX;TXQ2a2b7eBsrW$j-dv9TO_t@-2WyUgrOuamN=-`Z< ztnR*~*=(M0KUASGH$U|Yq-j#=t}5@Y%rYhFhs;3kh;neli9&6#!P0e$W-dm_lGCV<*rt(pD;p*7~<=Ke>90VHG4B8R(n!YLo6=}|>CN$SIvvEhR zlmB(*bl0Q*^$MEbI&>Fl(pW01nci-iHy!E{n*$EjWAF4-eQK_9z>ZL^vryQ3@LQLq1X(Dz?vKU6kTo*k=~Ts8VBa(2E@Ja{nITPUzRjaTTi zMy|pX6gOR(6W5IVuWeEXxjMuSuJc6h2s9g4f9ahWEpw` z&y^O4Kb0<6B7D9q3Lj-@YbXOEA~l?s!{A7-wYLWNOPDHH|{W#xzqfg?V+0Dy6@`i=l{K(-OAD5W$yJ$f4`pT@7J7< zIwCy~^>pb8u>$25U&z4@_(P!27lBJ{^&ves3rW- zYx$!R_@g5DqcZrTLil4#iEJr`1{g_ON@PokY$=f~#nMVgWJ`(c<2n0y&Q>C4A2(}6 z)RD7~=j`K#p7_x|ZfFc-OEL5ib(rqsk1fS?AjpM;GtA6pkg zGa%a(Lp2~<7ehB7TNg8eAX^thJ5fisDW%g^-V$%rX=~kSYu#yUZOH)YH;?z&$9wGK zJ>8}$J>8}fJ>8}$J>8}fJ>8}$J>8}fJ>8}$J>9mH9@DKoJyB-ftlyVR9LTZygmO!! zbg)!J@GKN3$C&h$z2fsm{F*p0HaE%ov$s$~4Jg#boHO$WoSep5!$XrS0=@u#fm_3w z$TMG^P%<1s;zEJxhC(|Hfp!|g?Ce#0I(yWL&K{9tXRoOb$8G4|^o8LCU4{pA8MfbL zhM~*wfiBbQU8dW+%rJBr9?)gFzss&Drqx}hja_Cix=h=<+-hLD*gVy3@^_p3-6nrG z`Q!O;$>c=ol8JJadBGi0f){>`Ff>>4T1w@>EaG<6LEY9WbM=gw8)=c*&M;q4O0dsJ zaxIoivHW7h?n&$ph06H#rJ`G*J57CR2sj8uUe>W98nv1(&z8pK3N`*$oGMWBn#n#> zK8PyOl)H$&T0>2CFDO(HT^rV*alF7h zAG2aZS7Sa7@ifyvKQ%G8#Yu6#+a~4^>`+pS>XPB*O#NrZFQ*a}(Ym|?4x zO0%vNHR!3=%p1{Hk7li*F++4c{iu}Nc5m7_SQy;36>Zk4w*LO|T~`+duW%Wz*t$DY z*!sL(n|8A0yO2~q(Y?bT;3y2b*Wj<(wrzNDq%g8+^NvBi!3a&02;BPy1}@(*w0TP* zx3P009dq5T;d<0Lj=I=T&9+9yh_-8c|48}Tndx0WaV+Vw=b;OR@d2KjCQ4~#;@O6o`bk5bBDIgmC*~P56PA`n3t7hWKX(8)j3KV z)m)X+dAsw{ng=m>pzN87=?4gRE5s3XnqLOJu->BFsOR!heM@C_vb=X5!a-aglznGc zf5YmQ>$qmFTrZJF2Eo$Au+b3)Q8o zVs+!7;(fzv*>q)2IlIjr1?3`YTNtXDb!acuL`z}RWfj0a6xOxh*7cyRZ}Rmv_s&Cc z>$|s1qm2&cO+njT&->a&9U~Qg??|tCAk{;I`M$!?RfTOsI|j@7C^FTt9d6!etb995 zGZ50yuBdOzmdZT6>V_nbAuoz#hbb^#GllwKd2mZKh!reu+Lp?UXnbs#As8+&;jv=G z^QFV&?Afw)dU~rA<_XzlOLG+B2f=obn<@Qh@Ds+sqx55>zg(izwxRJ&*-jf7a@}vb z9pR>MUDUa!FkHp#W4nNt40jZETO!+I=F?Cf`?bi%bqc25@}TT^yPBwp+RngxH%(8Q z8D2CdoqA;+MSTu^xfpjtXV77;G7Y*7i49A{m^Cj-;A+_YVm_mCwnrTWnJmV}%lo4o z_q8&H1eOG&*Bbkge#Nq9HS+oK>2k49n=3*9+xO?U?;0*(97#ViD4VugX&P@QT+}%@ zR=;M7u^&dS$9PPJT(qa432sfZ4K9QsS5L>2d}5kG@W$N;EAY1R!L1eQQZnY&5~g4C zy521#Q=*ySYI%0|H9IQBeNo5Nv-I9R(SjxIFMiFXq+Yo-3FfQ4jqJh&t5D>5`rj z`MNGKQ%=A2sYT){mbk;YIF2E4ycKf|hPuU|ZMD7|7=D_WIQf~8+JTvBerzv8SSn(O zDvFJ(vR#RpkW+=33+0EO44rl|6g;g@R}QqK^>`VKa=S}dort zH@Z=6%-OtU@6>c;C>Lo$Zn1OLj)rrmuoCxcAx1E%6kTs5NVtz4Fg_yBaN?T5gqR9_ zTB}DemuQYhy<+9!QA1i=WRbQkBCmyrw4IfS`RS51`F3mUyX?^K3g{(gR>zWC)mWIq zfmR>$qEJw1X61=FsO5BPX&N&fd|6Ht7Ro-;AKV9>QL7clW+!8wV_9!{HgC!29mn>o zhRLye^T=GOG_O6+L{pGnjrc-4)$_twrGlG-j?<`T~=D5tJD?H+Ic(8A}5^tX}f2 z)!N|hw78{)86x#kBZAG~D#Zn8#MKYMNEZ5MuelAUHLZR3@J2cs21k$*JqMQ-c)Q9+_jxM5wl7U;( zw{|!t9&p=S*Vb}PCWv7S59MOe6JcJ*vYSb44KihjyYut--&zzh74ZG-POjZrV%fAJ zYN~sqgiH~2Bll_4)ECD82|b8o)8&EJQtriu)&xNzRcfdblexnP*A0dw_mNp8I$1h4 zO-wYrk)_&5#W3u#X-)YWFQlv-F4Dn+b@|Rz9d1jrVuYl+#m2tONiy}s#9`%Q>Rygv z-XTEm&p2s!Gajn?JF6Mgo zmSf^~k>_{2D>9?)F7KU!+vvSc8`S*lHtSg+nP{d+EP}hI$I^`hqVyUvpldIy0$$pN zA?;Pr9+fUX0gH)Y?*uYGUw- zL1A*PF*lNC1Xz6Nezrp%>OWn>it>OVSoY*eP-}A(Ns@5du4R!iqwlv17^|OK{CKjV zut$+rpW*rOeP(gAOHiWz7Fa$W>WCrFCzNFzU8%x4muC8ENBlbJlHoht#HCU7{I+q# zN2Yye;iz(mo0mO9n3?A4gFIrW(21RHikKcWwQMNCDLY9kHs(zy=0V48!!Ahl4V(nl zn^YFB+hs(!t>t2UD10y`1N*Dh!;HGD;1f~TBdu(>B*s!|?@(>ibaiTMaH`cLaDC+1 zbI+!tA`n>pEq7_C(|#rd7JF53d)g8absGMTyy0~F=9aKNhZRjO!2L!DF>KOOwo_7U z@0eamTY3zu8aGLawY>l8*%z0qK~Zj=G%qpUqS5Gc`?g*t(ba^VNxN0?G1+5S+_)iw)7B(yc!9i(9meza`2A}cRUVl^4_i^K zjw9a2AHm2c=Bo)NZEPs~K8yRgRGg`5M4)h5CgaLD;T3a->XoU|LBd7KUMy+B5*Z<6 zRwHqU<-7Qh!X!@ZxR-vhsULONC3#0_(yquO!%eeaG8HVjOimC<3~-eT^)%L%koXiePHmb!b4m@=uRz1XDL8Sj+whRv#}7wOnmIw>^KAuZW; zskOVtI^SBFuVcme7Mfko6@_AF%#n5)6bNmYD9g%Lou=w3om&kF^rD`mUNmovO;$5< zrQsJqSHkcQHI}EPIT=ON3CqRmA*?@6`UnVwmD(Afo&J$vJjVDF@SOw;E0^=z^7~;$ z*UJil4WwU`lMeGVG}WS;qfQ2yh|sYrMwT(6mCVS6mZNS0@(h#4Bc{+V$2>0I^S?%= z-8;&&`)bf@MEvV8oDh$fQSR5U?L=LYuVV9tDAHKmm{v{NfGp*+R_pV|dkH-1hGtKV zQ%3{YJXE1~CBpk6bm%g%uN4gG*tx2vYbVC6Nj~PhGBP#%0;corv~lZazrtkaMyAS6 zwGSphWKGBo+ZYeej-iN2S{xz}&=l5!c}5-T9y=EdAEK#gi-R5H$!cNBO!Ii{k0N6R za8GCOtPnSu)Zxq;?zTGBP(`iWv-(Ff{}1B5UUl@m46C45vbcSw!mT zH~)_;k46(v?`;oe{+bq%t^-pn+xu~hn$Y*4ja`b8wlgXahAe(&Sau+E970PpYbvHM~`2c|6Lsnp_(p4NekO9{6so9W^nb z8=|2TfSCrn39hcpqS?ry94(4ARPOXgjcIh#7s*QbSu? zUc>nkS`E7Gyv3KnCI`KsSAv8I(PzLn6E-`+Xczr&HRN@(v!_9pZd8sgu_b!j`c|8a zlE*Z&8)oISy58q3q}o4(N7pdG-3bE{Y+ml76e*?$!N|NRgPog%zO}&!hl`e_HE+*J zwD{;9l-7gI^z(v5BBTT^V-h9mAbW;x9X!NlBXbl14Nek(!K!*R;j*fItU`kPJ|^tUTwUf5>TiJ|vNc zQ~MK*iLI{jS~HaQqG3{4wN8H|sv-dpm@08onw2;~CP@_~Z8q^l8$Uw#BfO?LT7z4= z;S7YVhu=t{o@llY^#t~RXCji}zoD)>{Zr&AhKSr)PFNn?ylhgn6J7bJyqJABwd0#wv=bDGTZ#%G3?Mo(A;a({)Tve)Sk4}Yb>HiuSE0IWCF{5oUl&@D|ml? z-h~r6O^k4igt#cWLBvffR2iJE7^b23vX8f_D@G~MKBB%&X4lUUeujCrm7#LTwQOGQ z7a^i~Le63r9~G0xW`Q-(C-WQYbXqXN$gVgAW1UMGirjl!I2WVA*&42U6GCQXtL?3< zLPl-$5e@9Ao!wiXGW-Qyy$@M-Y#s+%JQb`w0^4QmH%&slnBmwi#h{ofhTYZRN_2w# z&-6oDLXaOs+JuSvXvLlJ#sq_H7E^eRV>vz$fF+IH(Brk_5|QLYqMS$JvWU7Z*V$cS zW9As4^~Rl;&r{ZkLu=Q2uowPtisYJ4#{>*Fk$ORG)?Im`_=cMV{0A5N4|YOmeJv!!fx^K zh~~H=;Apk^={nppULD28&|ejBrE0C^XF=LfyJPN<{m)66ns?$hSjq_1i% zvA5Y)6`RP>sR$d5X)W3)Yv;&t!W%fDZQyYpjZ_O0-!XZ6AG!Z~E&GM*HgD67mx;tA zbFnr~NVGG1WSD2ggB~u_(JZtHj@Hb;<9HD!WXK82jTk56Qb~-ntFQt`h*q64(sOe} zv5gTZPGe6HH8%$ydAH*lc1{iAP%ADe+Vv`lmxNoXBr@4x-Wby~XvBjw^uf5dqh1qw zl2}Q^Lz!K$8_gC`D^dl4zWjKUMMk~{^}IKU$8I1PC8Al92wPYaQTiGxhM0dV*~INq z(o$yEQzyH6i6hB_qOPHunjlry2kFod^<%>6-!)sU)KqulvuKKUHu+mvTyvOev6QkI z!$tPlU<9}1CyD&wC@>+CB2{>aJK2~n84P5lF*5>%x-9o@M+wVE)z{^9736f%y1wM|YV)8Oov6y~W~mc^tkJZ!K2Plr}i)MWH^}Ntk{dW@f}3!?fc-m`2SU z!%6ZdPaY}Ber+`~w0A$uy6-LCm|3k-Tdt1G;p{@lGFCU-pLKRR5Z#*^!WJgyUMr&S z#CUE@MTC1=5hO*^!==(b(R9=kuo`|V$Yk2t-8!adXfNJbA2Z$vFrw1}*48mWFjBn~ zcvujWjUHKJnYUc73@@-2kS04u)MXpMu9_X_M@ZO5UEI|`INfZsMbi$Sr80QFA^&=Jv7+Ph?s8^wQX3Ugog1`?co8SxDXe{@Vq}Sg<)RjM6VF96nGziNk%bs&DjscFH*_zPar0VYTIQy4A3>A5=BKAe z+`$goZ6uZl%Ma{aEa2wHpnK#pHQKQ?Hz+yki(S>87U=*}TFTN*yl#omW*5%FK%|y0 zo-qP(OaFgj1$b0Oi8V#7*8DX`TO0b8dZMu3+mu_Y!>QIb*4v=xa~+!qc-zm4wD}O* zLk?Kod~iJD6$cv-kz{kNyxMC!dJ{rj!Z06b|LWmbQX|0H?$sEnD9}}6fK4>&XoN$l zHtY7`40~c3p~}G_5@lT+-XsOmbSmuEvhv)1?wP zBgd~up6@qB(jTMP8mOvBjA5i?luH{T4bKRsfk;DP`tdAqM;fVJM-^VPX5d0(5%@`G&Q9%V=GUG*1rEiL+tHAtslzY9$lesEr)^zkH>FI}UIdQY z&=BepdP!5osP_LPC+OW(Iv`)0l_kO{+-hf@3p1i2jWy6tUSm@=vHgt%b#B}`6IBz& zkv8lAP7i4cGz)3t7#!pARv36x6N@n;oidr`qz~?zpJ8>4_jCAYrUt{GJwW6K?7o@X z2O3f6VGxUJS~lJGz=jdM5pAqsuAnnr2gm&u^T(61~MrtIm$% z>Kyk~PI(4{{ePZCyPgd;&vz3ZGE;3WKVV21)&Y}~ z_M}1PW^pRDJ)(*s9;<*oJb^$y3<4=8XLclVc%3+gGpJcNnYUTf6>IN7!vi`yAvMFt z44Iw_Y0KKeT;RyDnU@XgZqm$6$*GaIIjv_(Mh<%(jRwzD!Mi(x@eZqIRUFs%ogMUL z(p?~dp0GoX3Q$;6!*?LR2aHx5J&E8EUm*^2zlMk^Hmwr>+m_Qc$EwG+kA(%#zI8$; zBR^2$%&`b+9J!MIsC<(HR^t)O(S+mBGygP8==9{Gu9d&Sb*_($i3iGT1?LrJ2T+5p zXKYMBQUhjA+NtUy9(YRnsPVPHS>X4Lkn(W!k0q>v!F4+*T3Gk|q+P>G%d^I$%6nSK zbQs}`)}gI<<~&zil%_{rTO8Y7GXO5|1IlKHSOB}xNdS9^vuP|6I($;4hD(|V){tsW zao&D|G+{b%g{1DymJax%3^fc1bKt|+h-@Qbxn#`-sK~^6xRy)1g@e~BO3wHutvatp z#sX>7IbWablagt7=aXuk-!#~Ts5lC35g5F7jZ*@- z)9rNXfIl}QZd#8NN(`FusQ$7=nDi#3W~a0lwvtTO$x*H~G6^-u(m9v0Cs5ZE#^%v@ zKob?!vaO>-knam4oTMpvKDjC!gV19ei;Zv^**Yqo{38b!u0J6|ozEsM*QcwcA1 zO>zAwhm*Elp9x|S^Jqw<{V)`_RMH>L8x$w^4%G%{ zs@A0t)0ERJyJW2u%>@w(LD9@-TV%tq9G8nEI;(?Fku55`e!f^IEQ0L0u13vlhDM_6 z?S!P$a?+(Ya3ilKXbPm8ozMY9*KmfiJ$}aW)ig!MJbL;NRtgEQ zI;bEaMl{i>dP0O@b^^|7hhFnUX??U#daksNVPLTL+h7H@-q?8+$113|lYQXeera+>`f+_39Be%u>lC0EG%P1D_F*Y1ZqN|m3=5^BX*tibi<75c! zOpV(e@cXq{b29}s`{HFHvFor-b#AfgC6pC`ZCbb$M40ET;Op*3=ykvq1Q_V2988b#kHw;dqzY45s@ zkFus}b1p>8abT4O#7})TeHc!zk(Dtvy;MR8h3>1a)U32>7m)xw$%c|l}Y2i#Sam?Zk^K2~Vc@C*@M_27Aj~i!mXtZ_KlSjtWk|MJ? z2d_n(sE&=}B>DYz|7{>4;eEnhRWD&SMeK1_)AZ_1unHQl-Krsh%Jf9Y?T&p8d9gdF zf_!dT=Iv%}C;xd#+o|PoWOhU6c6-rHT|$EB-NunD9AV)tz*;yh8}Dtn_ALi$VI`n? zN2R|O!4)nx!NqMIYixp8sOd$^VxfK4w=v6%a_V}0Ajhm?EwoxBW^-mn!~X1ePiVrG zAv?w5?Tc-{7`ue`J)6_ZjJ=JGXozSnIw>B0&%PVm<`a&IW5u2aQ)jw#x@L@lV-w-7N_(oP>8eL8aJZ#q_JG+T6i(TQ&^QP? z42^@CB<$o-4}0PpZNzYH;wimh!>#&E0O!gH&PbavUv`Qq`B>MbQ~>o+Hgmf9k)v}t zgw6Ji0?*uRYz_c(5o{)UZG_K_5Tk`gzPDi1Ll?)uNFL3O^03FQLV=d;C}P)cq1{@k zC$_j+ck86+xTfH;RP56r5#U$NZsSn1X-hWrW3OZbhQcm8;bKMqv!Q*QO$ultX%-!x zg4Ih9eQ9og$!^;Y7KjdH?iN9ymYF&8RYRCb+PXEuew}sn(BIfYthFc~Fic0hc$XUT zTM!@C!d?|;(+d0x(NNl+;+9QEL0xV~%NW)iS!zu$hmMjKahP`fXd%oQ2bVW(OH;RU zv5`8)*_k!VVd`w%qw9POj)|&9t=X>~1M#G3S{muk|4IIyaL1eX9#im-Yv0i(N%JO< z4t6jlw|u~?X>@0SunDXvq_^7g0ar>|QOv^1#KDTGgNaf!9}~7&nq>`a{Ac>s(zT=3 zsM}7_1kncBoG64~WtrSYj5gKUM1A8pFE{yGC|phvqT(&Ww!25>4!Ou}cZ$MbUuD{! zhOGjFF=!dWZN&<6guiuD>!FZV%{f8g*+sG@LGMRX%8Y*^sR*`o5GHn%_vP82q;CUg zvOB@MS*v3t+!_%G?cwmyhUB59M{!p*xrUe*@Nc_G()40u%QW&YN75iYg@><19cHiM ze2oK>Wr~v*&VMVZ`P5W|@;P(Dze=_<(9KO6{b<}C>D{K<-V+`I;m_yTG;WTowdZq~ zV*z{@2ZB?m{3LwDo_1Sxe$>g%|MIMtf&6*1p@6_~5;lxkrcc(0(!LSYer?O78}N8^ z)o@$#<&A?JIL(p8`E5AV;|{W%HP#dPnU(ZpiXNJ693||Tx$mf&5#FWe@+NDuOERZe1xsPD)w6Tuqwe3vwfLuSu6-}Q`xL4wY+%1H8~qW1kMn;pa) z#Fe(t<72x}tVky|hc+~>meRhZ>6opXEkz1u)hK8c#y67SNvfqKWJdsx%p8Jv;zqq` zHYi@W)ocj3TCTGZ(C_tbI~7DQiMW2-nRYeuHi}j|ztYQ}&L1>8RCLb&v3)!NXNGax zn2jDhL~w=ex71L&&NRH!RjEa1wwj8muSWzTkNKFP6L^A?Ea3k1Wa3ozluRbh5qy*Y zHelGaIkq@vJJc^{qMOaPa#JA@6Vp1kHEp;ENU75-!E2w`5@+?YX#9&Y71-1E+#xy% z4ba7{B^^}0l#sF_!y_&C*=Y`SXjr&gc-ouRXq4CS|QgebtntVwJ7I9!zjQc=8*JqaV@F)2F5fMjlpXQk7MEJ1mmEk5g-j#S-ZPte-?rJJ1W4MEBZp793k zE!#G!8nJcT8N8aeB0~y~MoL<1`%8{*irWarp;>Gvskk&pcgE=0;@n***9~7FGbc_4 zOwQOy?6$>;d<-UKXlSI{A|X>tZ%-hw8V#%qU-^bc1pRf3g?%%Uzp{{95JOR z)2O3@ zYpy$-hE7T-VQHN+UbTIgqE#4@8hMThmr%#8&f|9`nvf%>AEX8~o&?fY%!Vf;soO)w zk7}@J5glcsJFrW%jP6Jf$Rm|84IeUWyp=fBWkq*B4q?4oW-m+Xea$O*YoD_xoK{XJ zYsNN{o+E^gWkam0oH7z5cb{o(YJ~SX71XrTj`#G--D3IeS6;qz;J; z1OH>eBVv!04l1&TCN``k&4wEjq+tou25HzOSG=6V9OtV#!OFN}ir3o|g-6zOmZ0D2 zAw2mH%1vN#>%%{U;oGjpDMZNA2Sb6yP82XUy^+d}<6Mv8W zRJoQJ`FrU1j+p04w4XF)uNEJ>tR3Q9>FGqZW=b;*T8hP{C7w8<%?>q9H|<7g za9-(HFp2t#9F5Bcgi@dv8s3uZgql8bpp&g^LUHMSNUBDvJMnGfe< z-+v+|0RGanbek%M-Ll5E*GJ{;ZW7oVqKEb#Vw+Jzjl!^&NZeq%34!zxZ!L)hMibi~ z;pI|ySD8cFGZKEjC}29y$!t#iO7k51)x8`Fk9yFHY;FZvGv+_uV{rLy^IZJ4ez{xS zTa2NwSy%a=9GW#0m;y5k<7VqU`M-$Ni!i_T)|UuRM=M*Y*6Q$#*qB%yk#|By_ST57 zWR5=r~F3g^PW=sSCWPVJH*|?`nsT4hB-1JdGKgTK&JCzpHd6=?V#UWU}(DG zzCAX%H6iTMO)ZTW;j(WOt#mYlF<$sU1@FUyl{9VGXq=OiI^n~Z-NUnmf)>*q4T%PG zn00@k*SA z6vo>cP8%~!4%@O{Rr2mLFAcUh4?8j&ORt)~s=gy~PCT}x z8czi61_@8#FyZDYIVR4X!kg~C{12aYigtw7lIvsrn+{^ zU#rur%u!}BogGzIW#)0hV&e?pU>m(Z4LCtV%`Pyy%_vcR$=KdvL=%SG#7R4SL`Rx) z%G@yb*pO~N7WUo0^!SCQjR%2U)Jteuyc)rC)?wEo9&zo{X_~jJ_y9uN$RK9Vice04 zKiW6IV*-p?=yC}w@tRs48hz^H9Wv*+dDm>YmV#%_)PQgJLp1U_V$ICcQ1A$w=1&pu zTMYQrXxgFDY+3MAMe9eyvEAUYSVj{fN7q$+F;*3a&-0(Ev*wm)yJ6_6IkyEURAp_g z?ZDgfeQ0QNEKiHi{SmM$y)(AJVqi9QjNzs=RF#XzF7WmlmL78t>k>)@UdWD=_&|?X zvfU}efn@F&E;AZQ&xEm-Os0HU`mnBy7TChv?thG@&Yuvj%&qq~CH0wKOkInj)F&}x zRR9qjX;sI??)cn!UL6in6J<2Ur)g=C?=74vN!vjjsMqwM=}FtS#z0bu4`j!437c(v0$wxE(<44i-H?Ojyrml)#~ZHq z&Q`o`;A2!>JCD{WA$hglDwXnYHwY;`jKoF97MF%ln4&V8@@V{F$uGdkB;0T!#m;)v zxwP1C#<7J^n%w5#++k*G;bu;w-e>)@;@}O}M$EzW(H@po7Z#5fju;@mB08TX|7%x@(wRgCillh7tr}v%YPb^_gqdK=Vy@Cj%t4ov6t#R3>_wvtUz4 z&grBwdz!vG;M9;sNX5Q$*OW2RCbdwoFyG)K#$2-xQ(syDLx|WrQ<=5l7zK$kicT_W zs3Sjfa#H#ONlfI{#}WBRriS*M@+&l%pKV>8@5JiOP0dM8GUiD`s|(5Pm=0UR+ROPgY+*DtzXC)q~J4I9xL7`~i9WoEJScFkAK0TOOf zCg~z(zN)89Yv#X>(vs~6md7YEs-i5xvwJDXR4e5`Tr;{p;2}}OGLkaygw)!s;l{FD zf_wtcAarKtVgE*Zq zXxqy}K>=y$*jF!zM~Yh6%W0q?#KdaiA5N~7me`a#)W3c2dPj=m2T`y8YIh>)0xRA)?!$+ht4`bXN|80_LrnbC{|EyGUa7Tx(?D7nn-TRZIiMX39m1s?=2@o1EEbiYapJ6eo1KzHn6{M`?V1 zFGY^c?k({$3(cpreA4(hk*q#tniGWlJzef^A%B1CO3EDj^=o83j(^AVul};OY#s2p z;BlqtI-h^*`KNrhk?%GV+PU{vo4bkl>+{`1zI(`bfzQNWpKmMoKmPg8D=P0n@;ykt zuL0J%yvnD4yZCo9|CDd(mbUB?Kd$n_iC`Wvc{cEO5C2Z!pYkm%wq+Oi@n25^xJ!9; zy@-E5ckit)(cbn<=0+0zd-c5j?c?9iT)rcBw`GrvEH@(-_joZwN`F9fk^vvqp z+p??YWin@R@5@u(EdO4?KjquZzn_rrC*=DF9#Xz1^3UgcE%&Oc-n05H%Dd3^J%F}f>|9rl!H?Plb{rT~kGfj&9pReD0Tt1aBO1@F@eV{YW*zRtBkH0EU`A)fa zefE^j6AX6Ajr&go`8JSm1NmNXw$EkTD)faQ-}Hm)v(r0H$c(wLI&QD>!vw!lq%scfGclq1@4~rr?1ONa4 diff --git a/tier1/KeyValues.cpp b/tier1/KeyValues.cpp new file mode 100644 index 00000000..26623c09 --- /dev/null +++ b/tier1/KeyValues.cpp @@ -0,0 +1,2539 @@ +//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#if defined( _WIN32 ) && !defined( _X360 ) +#include // for WideCharToMultiByte and MultiByteToWideChar +#elif defined( _LINUX ) || defined( __APPLE__ ) +#include // wcslen() +#define _alloca alloca +#endif + +#include +#include "filesystem.h" +#include + +#include +#include +#include "tier0/dbg.h" +#include "tier0/mem.h" +#include "utlvector.h" +#include "utlbuffer.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include + +static const char * s_LastFileLoadingFrom = "unknown"; // just needed for error messages + +#define KEYVALUES_TOKEN_SIZE 1024 +static char s_pTokenBuf[KEYVALUES_TOKEN_SIZE]; + + +#define INTERNALWRITE( pData, len ) InternalWrite( filesystem, f, pBuf, pData, len ) + + +// a simple class to keep track of a stack of valid parsed symbols +const int MAX_ERROR_STACK = 64; +class CKeyValuesErrorStack +{ +public: + CKeyValuesErrorStack() : m_pFilename("NULL"), m_errorIndex(0), m_maxErrorIndex(0) {} + + void SetFilename( const char *pFilename ) + { + m_pFilename = pFilename; + m_maxErrorIndex = 0; + } + + // entering a new keyvalues block, save state for errors + // Not save symbols instead of pointers because the pointers can move! + int Push( int symName ) + { + if ( m_errorIndex < MAX_ERROR_STACK ) + { + m_errorStack[m_errorIndex] = symName; + } + m_errorIndex++; + m_maxErrorIndex = MAX( m_maxErrorIndex, (m_errorIndex-1) ); + return m_errorIndex-1; + } + + // exiting block, error isn't in this block, remove. + void Pop() + { + m_errorIndex--; + Assert(m_errorIndex>=0); + } + + // Allows you to keep the same stack level, but change the name as you parse peers + void Reset( int stackLevel, int symName ) + { + Assert( stackLevel >= 0 && stackLevel < m_errorIndex ); + m_errorStack[stackLevel] = symName; + } + + // Hit an error, report it and the parsing stack for context + void ReportError( const char *pError ) + { + Warning( "KeyValues Error: %s in file %s\n", pError, m_pFilename ); + for ( int i = 0; i < m_maxErrorIndex; i++ ) + { + if ( m_errorStack[i] != INVALID_KEY_SYMBOL ) + { + if ( i < m_errorIndex ) + { + Warning( "%s, ", KeyValuesSystem()->GetStringForSymbol(m_errorStack[i]) ); + } + else + { + Warning( "(*%s*), ", KeyValuesSystem()->GetStringForSymbol(m_errorStack[i]) ); + } + } + } + Warning( "\n" ); + } + +private: + int m_errorStack[MAX_ERROR_STACK]; + const char *m_pFilename; + int m_errorIndex; + int m_maxErrorIndex; +} g_KeyValuesErrorStack; + + +// a simple helper that creates stack entries as it goes in & out of scope +class CKeyErrorContext +{ +public: + CKeyErrorContext( KeyValues *pKv ) + { + Init( pKv->GetNameSymbol() ); + } + + ~CKeyErrorContext() + { + g_KeyValuesErrorStack.Pop(); + } + CKeyErrorContext( int symName ) + { + Init( symName ); + } + void Reset( int symName ) + { + g_KeyValuesErrorStack.Reset( m_stackLevel, symName ); + } +private: + void Init( int symName ) + { + m_stackLevel = g_KeyValuesErrorStack.Push( symName ); + } + + int m_stackLevel; +}; + +// Uncomment this line to hit the ~CLeakTrack assert to see what's looking like it's leaking +// #define LEAKTRACK + +#ifdef LEAKTRACK + +class CLeakTrack +{ +public: + CLeakTrack() + { + } + ~CLeakTrack() + { + if ( keys.Count() != 0 ) + { + Assert( 0 ); + } + } + + struct kve + { + KeyValues *kv; + char name[ 256 ]; + }; + + void AddKv( KeyValues *kv, char const *name ) + { + kve k; + Q_strncpy( k.name, name ? name : "NULL", sizeof( k.name ) ); + k.kv = kv; + + keys.AddToTail( k ); + } + + void RemoveKv( KeyValues *kv ) + { + int c = keys.Count(); + for ( int i = 0; i < c; i++ ) + { + if ( keys[i].kv == kv ) + { + keys.Remove( i ); + break; + } + } + } + + CUtlVector< kve > keys; +}; + +static CLeakTrack track; + +#define TRACK_KV_ADD( ptr, name ) track.AddKv( ptr, name ) +#define TRACK_KV_REMOVE( ptr ) track.RemoveKv( ptr ) + +#else + +#define TRACK_KV_ADD( ptr, name ) +#define TRACK_KV_REMOVE( ptr ) + +#endif + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +KeyValues::KeyValues( const char *setName ) +{ + TRACK_KV_ADD( this, setName ); + + Init(); + SetName ( setName ); +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +KeyValues::KeyValues( const char *setName, const char *firstKey, const char *firstValue ) +{ + TRACK_KV_ADD( this, setName ); + + Init(); + SetName( setName ); + SetString( firstKey, firstValue ); +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +KeyValues::KeyValues( const char *setName, const char *firstKey, const wchar_t *firstValue ) +{ + TRACK_KV_ADD( this, setName ); + + Init(); + SetName( setName ); + SetWString( firstKey, firstValue ); +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +KeyValues::KeyValues( const char *setName, const char *firstKey, int firstValue ) +{ + TRACK_KV_ADD( this, setName ); + + Init(); + SetName( setName ); + SetInt( firstKey, firstValue ); +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +KeyValues::KeyValues( const char *setName, const char *firstKey, const char *firstValue, const char *secondKey, const char *secondValue ) +{ + TRACK_KV_ADD( this, setName ); + + Init(); + SetName( setName ); + SetString( firstKey, firstValue ); + SetString( secondKey, secondValue ); +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +KeyValues::KeyValues( const char *setName, const char *firstKey, int firstValue, const char *secondKey, int secondValue ) +{ + TRACK_KV_ADD( this, setName ); + + Init(); + SetName( setName ); + SetInt( firstKey, firstValue ); + SetInt( secondKey, secondValue ); +} + +//----------------------------------------------------------------------------- +// Purpose: Initialize member variables +//----------------------------------------------------------------------------- +void KeyValues::Init() +{ + m_iKeyName = INVALID_KEY_SYMBOL; + m_iDataType = TYPE_NONE; + + m_pSub = NULL; + m_pPeer = NULL; + m_pChain = NULL; + + m_sValue = NULL; + m_wsValue = NULL; + m_pValue = NULL; + + m_bHasEscapeSequences = false; + + // for future proof + memset( unused, 0, sizeof(unused) ); +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +KeyValues::~KeyValues() +{ + TRACK_KV_REMOVE( this ); + + RemoveEverything(); +} + +//----------------------------------------------------------------------------- +// Purpose: remove everything +//----------------------------------------------------------------------------- +void KeyValues::RemoveEverything() +{ + KeyValues *dat; + KeyValues *datNext = NULL; + for ( dat = m_pSub; dat != NULL; dat = datNext ) + { + datNext = dat->m_pPeer; + dat->m_pPeer = NULL; + delete dat; + } + + for ( dat = m_pPeer; dat && dat != this; dat = datNext ) + { + datNext = dat->m_pPeer; + dat->m_pPeer = NULL; + delete dat; + } + + delete [] m_sValue; + m_sValue = NULL; + delete [] m_wsValue; + m_wsValue = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *f - +//----------------------------------------------------------------------------- + +void KeyValues::RecursiveSaveToFile( CUtlBuffer& buf, int indentLevel ) +{ + RecursiveSaveToFile( NULL, FILESYSTEM_INVALID_HANDLE, &buf, indentLevel ); +} + +//----------------------------------------------------------------------------- +// Adds a chain... if we don't find stuff in this keyvalue, we'll look +// in the one we're chained to. +//----------------------------------------------------------------------------- + +void KeyValues::ChainKeyValue( KeyValues* pChain ) +{ + m_pChain = pChain; +} + +//----------------------------------------------------------------------------- +// Purpose: Get the name of the current key section +//----------------------------------------------------------------------------- +const char *KeyValues::GetName( void ) const +{ + return KeyValuesSystem()->GetStringForSymbol(m_iKeyName); +} + +//----------------------------------------------------------------------------- +// Purpose: Get the symbol name of the current key section +//----------------------------------------------------------------------------- +int KeyValues::GetNameSymbol() const +{ + return m_iKeyName; +} + + +//----------------------------------------------------------------------------- +// Purpose: Read a single token from buffer (0 terminated) +//----------------------------------------------------------------------------- +#ifdef _MSC_VER +#pragma warning (disable:4706) +#endif +const char *KeyValues::ReadToken( CUtlBuffer &buf, bool &wasQuoted, bool &wasConditional ) +{ + wasQuoted = false; + wasConditional = false; + + if ( !buf.IsValid() ) + return NULL; + + // eating white spaces and remarks loop + while ( true ) + { + buf.EatWhiteSpace(); + if ( !buf.IsValid() ) + return NULL; // file ends after reading whitespaces + + // stop if it's not a comment; a new token starts here + if ( !buf.EatCPPComment() ) + break; + } + + const char *c = (const char*)buf.PeekGet( sizeof(char), 0 ); + if ( !c ) + return NULL; + + // read quoted strings specially + if ( *c == '\"' ) + { + wasQuoted = true; + buf.GetDelimitedString( m_bHasEscapeSequences ? GetCStringCharConversion() : GetNoEscCharConversion(), + s_pTokenBuf, KEYVALUES_TOKEN_SIZE ); + return s_pTokenBuf; + } + + if ( *c == '{' || *c == '}' ) + { + // it's a control char, just add this one char and stop reading + s_pTokenBuf[0] = *c; + s_pTokenBuf[1] = 0; + buf.SeekGet( CUtlBuffer::SEEK_CURRENT, 1 ); + return s_pTokenBuf; + } + + // read in the token until we hit a whitespace or a control character + bool bReportedError = false; + bool bConditionalStart = false; + int nCount = 0; + while ( (c = (const char*)buf.PeekGet( sizeof(char), 0 )) ) + { + // end of file + if ( *c == 0 ) + break; + + // break if any control character appears in non quoted tokens + if ( *c == '"' || *c == '{' || *c == '}' ) + break; + + if ( *c == '[' ) + bConditionalStart = true; + + if ( *c == ']' && bConditionalStart ) + { + wasConditional = true; + } + + // break on whitespace + if ( isspace(*c) ) + break; + + if (nCount < (KEYVALUES_TOKEN_SIZE-1) ) + { + s_pTokenBuf[nCount++] = *c; // add char to buffer + } + else if ( !bReportedError ) + { + bReportedError = true; + g_KeyValuesErrorStack.ReportError(" ReadToken overflow" ); + } + + buf.SeekGet( CUtlBuffer::SEEK_CURRENT, 1 ); + } + s_pTokenBuf[ nCount ] = 0; + return s_pTokenBuf; +} +#ifdef _MSC_VER +#pragma warning (default:4706) +#endif + + +//----------------------------------------------------------------------------- +// Purpose: if parser should translate escape sequences ( /n, /t etc), set to true +//----------------------------------------------------------------------------- +void KeyValues::UsesEscapeSequences(bool state) +{ + m_bHasEscapeSequences = state; +} + + +//----------------------------------------------------------------------------- +// Purpose: Load keyValues from disk +//----------------------------------------------------------------------------- +bool KeyValues::LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID ) +{ + Assert(filesystem); +#ifndef _LINUX + Assert( IsX360() || ( IsPC() && _heapchk() == _HEAPOK ) ); +#endif + + FileHandle_t f = filesystem->Open(resourceName, "rb", pathID); + if ( !f ) + return false; + + s_LastFileLoadingFrom = (char*)resourceName; + + // load file into a null-terminated buffer + int fileSize = filesystem->Size( f ); + unsigned bufSize = ((IFileSystem *)filesystem)->GetOptimalReadSize( f, fileSize + 1 ); + + char *buffer = (char*)((IFileSystem *)filesystem)->AllocOptimalReadBuffer( f, bufSize ); + Assert( buffer ); + + // read into local buffer + bool bRetOK = ( ((IFileSystem *)filesystem)->ReadEx( buffer, bufSize, fileSize, f ) != 0 ); + + filesystem->Close( f ); // close file after reading + + if ( bRetOK ) + { + buffer[fileSize] = 0; // null terminate file as EOF + bRetOK = LoadFromBuffer( resourceName, buffer, filesystem ); + } + + ((IFileSystem *)filesystem)->FreeOptimalReadBuffer( buffer ); + + return bRetOK; +} + +//----------------------------------------------------------------------------- +// Purpose: Save the keyvalues to disk +// Creates the path to the file if it doesn't exist +//----------------------------------------------------------------------------- +bool KeyValues::SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID ) +{ + // create a write file + FileHandle_t f = filesystem->Open(resourceName, "wb", pathID); + + if ( f == FILESYSTEM_INVALID_HANDLE ) + { + DevMsg(1, "KeyValues::SaveToFile: couldn't open file \"%s\" in path \"%s\".\n", + resourceName?resourceName:"NULL", pathID?pathID:"NULL" ); + return false; + } + + RecursiveSaveToFile(filesystem, f, NULL, 0); + filesystem->Close(f); + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Write out a set of indenting +//----------------------------------------------------------------------------- +void KeyValues::WriteIndents( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel ) +{ + for ( int i = 0; i < indentLevel; i++ ) + { + INTERNALWRITE( "\t", 1 ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Write out a string where we convert the double quotes to backslash double quote +//----------------------------------------------------------------------------- +void KeyValues::WriteConvertedString( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const char *pszString ) +{ + // handle double quote chars within the string + // the worst possible case is that the whole string is quotes + int len = Q_strlen(pszString); + char *convertedString = (char *) _alloca ((len + 1) * sizeof(char) * 2); + int j=0; + for (int i=0; i <= len; i++) + { + if (pszString[i] == '\"') + { + convertedString[j] = '\\'; + j++; + } + else if ( m_bHasEscapeSequences && pszString[i] == '\\' ) + { + convertedString[j] = '\\'; + j++; + } + convertedString[j] = pszString[i]; + j++; + } + + INTERNALWRITE(convertedString, strlen(convertedString)); +} + + +void KeyValues::InternalWrite( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const void *pData, int len ) +{ + if ( filesystem ) + { + filesystem->Write( pData, len, f ); + } + + if ( pBuf ) + { + pBuf->Put( pData, len ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Save keyvalues from disk, if subkey values are detected, calls +// itself to save those +//----------------------------------------------------------------------------- +void KeyValues::RecursiveSaveToFile( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel ) +{ + // write header + WriteIndents( filesystem, f, pBuf, indentLevel ); + INTERNALWRITE("\"", 1); + WriteConvertedString(filesystem, f, pBuf, GetName()); + INTERNALWRITE("\"\n", 2); + WriteIndents( filesystem, f, pBuf, indentLevel ); + INTERNALWRITE("{\n", 2); + + // loop through all our keys writing them to disk + for ( KeyValues *dat = m_pSub; dat != NULL; dat = dat->m_pPeer ) + { + if ( dat->m_pSub ) + { + dat->RecursiveSaveToFile( filesystem, f, pBuf, indentLevel + 1 ); + } + else + { + // only write non-empty keys + + switch (dat->m_iDataType) + { + case TYPE_STRING: + { + if (dat->m_sValue && *(dat->m_sValue)) + { + WriteIndents(filesystem, f, pBuf, indentLevel + 1); + INTERNALWRITE("\"", 1); + WriteConvertedString(filesystem, f, pBuf, dat->GetName()); + INTERNALWRITE("\"\t\t\"", 4); + + WriteConvertedString(filesystem, f, pBuf, dat->m_sValue); + + INTERNALWRITE("\"\n", 2); + } + break; + } + case TYPE_WSTRING: + { +#ifdef _WIN32 + if ( dat->m_wsValue ) + { + static char buf[KEYVALUES_TOKEN_SIZE]; + // make sure we have enough space + Assert(::WideCharToMultiByte(CP_UTF8, 0, dat->m_wsValue, -1, NULL, 0, NULL, NULL) < KEYVALUES_TOKEN_SIZE); + int result = ::WideCharToMultiByte(CP_UTF8, 0, dat->m_wsValue, -1, buf, KEYVALUES_TOKEN_SIZE, NULL, NULL); + if (result) + { + WriteIndents(filesystem, f, pBuf, indentLevel + 1); + INTERNALWRITE("\"", 1); + INTERNALWRITE(dat->GetName(), Q_strlen(dat->GetName())); + INTERNALWRITE("\"\t\t\"", 4); + + WriteConvertedString(filesystem, f, pBuf, buf); + + INTERNALWRITE("\"\n", 2); + } + } +#endif + break; + } + + case TYPE_INT: + { + WriteIndents(filesystem, f, pBuf, indentLevel + 1); + INTERNALWRITE("\"", 1); + INTERNALWRITE(dat->GetName(), Q_strlen(dat->GetName())); + INTERNALWRITE("\"\t\t\"", 4); + + char buf[32]; + Q_snprintf(buf, sizeof( buf ), "%d", dat->m_iValue); + + INTERNALWRITE(buf, Q_strlen(buf)); + INTERNALWRITE("\"\n", 2); + break; + } + + case TYPE_UINT64: + { + WriteIndents(filesystem, f, pBuf, indentLevel + 1); + INTERNALWRITE("\"", 1); + INTERNALWRITE(dat->GetName(), Q_strlen(dat->GetName())); + INTERNALWRITE("\"\t\t\"", 4); + + char buf[32]; + // write "0x" + 16 char 0-padded hex encoded 64 bit value + Q_snprintf( buf, sizeof( buf ), "0x%016I64X", *( (uint64 *)dat->m_sValue ) ); + + INTERNALWRITE(buf, Q_strlen(buf)); + INTERNALWRITE("\"\n", 2); + break; + } + + case TYPE_FLOAT: + { + WriteIndents(filesystem, f, pBuf, indentLevel + 1); + INTERNALWRITE("\"", 1); + INTERNALWRITE(dat->GetName(), Q_strlen(dat->GetName())); + INTERNALWRITE("\"\t\t\"", 4); + + char buf[48]; + Q_snprintf(buf, sizeof( buf ), "%f", dat->m_flValue); + + INTERNALWRITE(buf, Q_strlen(buf)); + INTERNALWRITE("\"\n", 2); + break; + } + case TYPE_COLOR: + DevMsg(1, "KeyValues::RecursiveSaveToFile: TODO, missing code for TYPE_COLOR.\n"); + break; + + default: + break; + } + } + } + + // write tail + WriteIndents(filesystem, f, pBuf, indentLevel); + INTERNALWRITE("}\n", 2); +} + +//----------------------------------------------------------------------------- +// Purpose: looks up a key by symbol name +//----------------------------------------------------------------------------- +KeyValues *KeyValues::FindKey(int keySymbol) const +{ + for (KeyValues *dat = m_pSub; dat != NULL; dat = dat->m_pPeer) + { + if (dat->m_iKeyName == keySymbol) + return dat; + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Find a keyValue, create it if it is not found. +// Set bCreate to true to create the key if it doesn't already exist +// (which ensures a valid pointer will be returned) +//----------------------------------------------------------------------------- +KeyValues *KeyValues::FindKey(const char *keyName, bool bCreate) +{ + // return the current key if a NULL subkey is asked for + if (!keyName || !keyName[0]) + return this; + + // look for '/' characters deliminating sub fields + char szBuf[256]; + const char *subStr = strchr(keyName, '/'); + const char *searchStr = keyName; + + // pull out the substring if it exists + if (subStr) + { + int size = subStr - keyName; + Q_memcpy( szBuf, keyName, size ); + szBuf[size] = 0; + searchStr = szBuf; + } + + // lookup the symbol for the search string + HKeySymbol iSearchStr = KeyValuesSystem()->GetSymbolForString( searchStr, bCreate ); + if ( iSearchStr == INVALID_KEY_SYMBOL ) + { + // not found, couldn't possibly be in key value list + return NULL; + } + + KeyValues *lastItem = NULL; + KeyValues *dat; + // find the searchStr in the current peer list + for (dat = m_pSub; dat != NULL; dat = dat->m_pPeer) + { + lastItem = dat; // record the last item looked at (for if we need to append to the end of the list) + + // symbol compare + if (dat->m_iKeyName == iSearchStr) + { + break; + } + } + + if ( !dat && m_pChain ) + { + dat = m_pChain->FindKey(keyName, false); + } + + // make sure a key was found + if (!dat) + { + if (bCreate) + { + // we need to create a new key + dat = new KeyValues( searchStr ); +// Assert(dat != NULL); + + // insert new key at end of list + if (lastItem) + { + lastItem->m_pPeer = dat; + } + else + { + m_pSub = dat; + } + dat->m_pPeer = NULL; + + // a key graduates to be a submsg as soon as it's m_pSub is set + // this should be the only place m_pSub is set + m_iDataType = TYPE_NONE; + } + else + { + return NULL; + } + } + + // if we've still got a subStr we need to keep looking deeper in the tree + if ( subStr ) + { + // recursively chain down through the paths in the string + return dat->FindKey(subStr + 1, bCreate); + } + + return dat; +} + +//----------------------------------------------------------------------------- +// Purpose: Create a new key, with an autogenerated name. +// Name is guaranteed to be an integer, of value 1 higher than the highest +// other integer key name +//----------------------------------------------------------------------------- +KeyValues *KeyValues::CreateNewKey() +{ + int newID = 1; + + // search for any key with higher values + for (KeyValues *dat = m_pSub; dat != NULL; dat = dat->m_pPeer) + { + // case-insensitive string compare + int val = atoi(dat->GetName()); + if (newID <= val) + { + newID = val + 1; + } + } + + char buf[12]; + Q_snprintf( buf, sizeof(buf), "%d", newID ); + + return CreateKey( buf ); +} + + +//----------------------------------------------------------------------------- +// Create a key +//----------------------------------------------------------------------------- +KeyValues* KeyValues::CreateKey( const char *keyName ) +{ + // key wasn't found so just create a new one + KeyValues* dat = new KeyValues( keyName ); + + dat->UsesEscapeSequences( m_bHasEscapeSequences != 0 ); // use same format as parent does + + // add into subkey list + AddSubKey( dat ); + + return dat; +} + + +//----------------------------------------------------------------------------- +// Adds a subkey. Make sure the subkey isn't a child of some other keyvalues +//----------------------------------------------------------------------------- +void KeyValues::AddSubKey( KeyValues *pSubkey ) +{ + // Make sure the subkey isn't a child of some other keyvalues + Assert( pSubkey->m_pPeer == NULL ); + + // add into subkey list + if ( m_pSub == NULL ) + { + m_pSub = pSubkey; + } + else + { + KeyValues *pTempDat = m_pSub; + while ( pTempDat->GetNextKey() != NULL ) + { + pTempDat = pTempDat->GetNextKey(); + } + + pTempDat->SetNextKey( pSubkey ); + } +} + + + +//----------------------------------------------------------------------------- +// Purpose: Remove a subkey from the list +//----------------------------------------------------------------------------- +void KeyValues::RemoveSubKey(KeyValues *subKey) +{ + if (!subKey) + return; + + // check the list pointer + if (m_pSub == subKey) + { + m_pSub = subKey->m_pPeer; + } + else + { + // look through the list + KeyValues *kv = m_pSub; + while (kv->m_pPeer) + { + if (kv->m_pPeer == subKey) + { + kv->m_pPeer = subKey->m_pPeer; + break; + } + + kv = kv->m_pPeer; + } + } + + subKey->m_pPeer = NULL; +} + + + +//----------------------------------------------------------------------------- +// Purpose: Return the first subkey in the list +//----------------------------------------------------------------------------- +KeyValues *KeyValues::GetFirstSubKey() +{ + return m_pSub; +} + +//----------------------------------------------------------------------------- +// Purpose: Return the next subkey +//----------------------------------------------------------------------------- +KeyValues *KeyValues::GetNextKey() +{ + return m_pPeer; +} + +//----------------------------------------------------------------------------- +// Purpose: Sets this key's peer to the KeyValues passed in +//----------------------------------------------------------------------------- +void KeyValues::SetNextKey( KeyValues *pDat ) +{ + m_pPeer = pDat; +} + + +KeyValues* KeyValues::GetFirstTrueSubKey() +{ + KeyValues *pRet = m_pSub; + while ( pRet && pRet->m_iDataType != TYPE_NONE ) + pRet = pRet->m_pPeer; + + return pRet; +} + +KeyValues* KeyValues::GetNextTrueSubKey() +{ + KeyValues *pRet = m_pPeer; + while ( pRet && pRet->m_iDataType != TYPE_NONE ) + pRet = pRet->m_pPeer; + + return pRet; +} + +KeyValues* KeyValues::GetFirstValue() +{ + KeyValues *pRet = m_pSub; + while ( pRet && pRet->m_iDataType == TYPE_NONE ) + pRet = pRet->m_pPeer; + + return pRet; +} + +KeyValues* KeyValues::GetNextValue() +{ + KeyValues *pRet = m_pPeer; + while ( pRet && pRet->m_iDataType == TYPE_NONE ) + pRet = pRet->m_pPeer; + + return pRet; +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the integer value of a keyName. Default value is returned +// if the keyName can't be found. +//----------------------------------------------------------------------------- +int KeyValues::GetInt( const char *keyName, int defaultValue ) +{ + KeyValues *dat = FindKey( keyName, false ); + if ( dat ) + { + switch ( dat->m_iDataType ) + { + case TYPE_STRING: + return atoi(dat->m_sValue); + case TYPE_WSTRING: +#ifdef _WIN32 + return _wtoi(dat->m_wsValue); +#else + DevMsg( "TODO: implement _wtoi\n"); + return 0; +#endif + case TYPE_FLOAT: + return (int)dat->m_flValue; + case TYPE_UINT64: + // can't convert, since it would lose data + Assert(0); + return 0; + case TYPE_INT: + case TYPE_PTR: + default: + return dat->m_iValue; + }; + } + return defaultValue; +} + +//----------------------------------------------------------------------------- +// Purpose: Get the integer value of a keyName. Default value is returned +// if the keyName can't be found. +//----------------------------------------------------------------------------- +uint64 KeyValues::GetUint64( const char *keyName, uint64 defaultValue ) +{ + KeyValues *dat = FindKey( keyName, false ); + if ( dat ) + { + switch ( dat->m_iDataType ) + { + case TYPE_STRING: + return atoi(dat->m_sValue); + case TYPE_WSTRING: +#ifdef _WIN32 + return _wtoi(dat->m_wsValue); +#else + AssertFatal( 0 ); + return 0; +#endif + case TYPE_FLOAT: + return (int)dat->m_flValue; + case TYPE_UINT64: + return *((uint64 *)dat->m_sValue); + case TYPE_INT: + case TYPE_PTR: + default: + return dat->m_iValue; + }; + } + return defaultValue; +} + +//----------------------------------------------------------------------------- +// Purpose: Get the pointer value of a keyName. Default value is returned +// if the keyName can't be found. +//----------------------------------------------------------------------------- +void *KeyValues::GetPtr( const char *keyName, void *defaultValue ) +{ + KeyValues *dat = FindKey( keyName, false ); + if ( dat ) + { + switch ( dat->m_iDataType ) + { + case TYPE_PTR: + return dat->m_pValue; + + case TYPE_WSTRING: + case TYPE_STRING: + case TYPE_FLOAT: + case TYPE_INT: + case TYPE_UINT64: + default: + return NULL; + }; + } + return defaultValue; +} + +//----------------------------------------------------------------------------- +// Purpose: Get the float value of a keyName. Default value is returned +// if the keyName can't be found. +//----------------------------------------------------------------------------- +float KeyValues::GetFloat( const char *keyName, float defaultValue ) +{ + KeyValues *dat = FindKey( keyName, false ); + if ( dat ) + { + switch ( dat->m_iDataType ) + { + case TYPE_STRING: + return (float)atof(dat->m_sValue); + case TYPE_WSTRING: +#ifdef _WIN32 + return (float) _wtof(dat->m_wsValue); // no wtof +#else + Assert(0); + return 0.; +#endif + case TYPE_FLOAT: + return dat->m_flValue; + case TYPE_INT: + return (float)dat->m_iValue; + case TYPE_UINT64: + return (float)(*((uint64 *)dat->m_sValue)); + case TYPE_PTR: + default: + return 0.0f; + }; + } + return defaultValue; +} + +//----------------------------------------------------------------------------- +// Purpose: Get the string pointer of a keyName. Default value is returned +// if the keyName can't be found. +//----------------------------------------------------------------------------- +const char *KeyValues::GetString( const char *keyName, const char *defaultValue ) +{ + KeyValues *dat = FindKey( keyName, false ); + if ( dat ) + { + // convert the data to string form then return it + char buf[64]; + switch ( dat->m_iDataType ) + { + case TYPE_FLOAT: + Q_snprintf( buf, sizeof( buf ), "%f", dat->m_flValue ); + SetString( keyName, buf ); + break; + case TYPE_INT: + case TYPE_PTR: + Q_snprintf( buf, sizeof( buf ), "%d", dat->m_iValue ); + SetString( keyName, buf ); + break; + case TYPE_UINT64: + Q_snprintf( buf, sizeof( buf ), "%I64i", *((uint64 *)(dat->m_sValue)) ); + SetString( keyName, buf ); + break; + + case TYPE_WSTRING: + { +#ifdef _WIN32 + // convert the string to char *, set it for future use, and return it + char wideBuf[512]; + int result = ::WideCharToMultiByte(CP_UTF8, 0, dat->m_wsValue, -1, wideBuf, 512, NULL, NULL); + if ( result ) + { + // note: this will copy wideBuf + SetString( keyName, wideBuf ); + } + else + { + return defaultValue; + } +#endif + break; + } + case TYPE_STRING: + break; + default: + return defaultValue; + }; + + return dat->m_sValue; + } + return defaultValue; +} + +const wchar_t *KeyValues::GetWString( const char *keyName, const wchar_t *defaultValue) +{ +#ifdef _WIN32 + KeyValues *dat = FindKey( keyName, false ); + if ( dat ) + { + wchar_t wbuf[64]; + switch ( dat->m_iDataType ) + { + case TYPE_FLOAT: + swprintf(wbuf, L"%f", dat->m_flValue); + SetWString( keyName, wbuf); + break; + case TYPE_INT: + case TYPE_PTR: + swprintf( wbuf, L"%d", dat->m_iValue ); + SetWString( keyName, wbuf ); + break; + case TYPE_UINT64: + { + swprintf( wbuf, L"%I64i", *((uint64 *)(dat->m_sValue)) ); + SetWString( keyName, wbuf ); + } + break; + + case TYPE_WSTRING: + break; + case TYPE_STRING: + { + static wchar_t wbuftemp[512]; // convert to wide + int result = ::MultiByteToWideChar(CP_UTF8, 0, dat->m_sValue, -1, wbuftemp, 512); + if ( result ) + { + SetWString( keyName, wbuftemp); + } + else + { + return defaultValue; + } + break; + } + default: + return defaultValue; + }; + + return (const wchar_t* )dat->m_wsValue; + } +#else + DevMsg("TODO: implement wide char functions\n"); +#endif + return defaultValue; +} + +//----------------------------------------------------------------------------- +// Purpose: Gets a color +//----------------------------------------------------------------------------- +Color KeyValues::GetColor( const char *keyName ) +{ + Color color(0, 0, 0, 0); + KeyValues *dat = FindKey( keyName, false ); + if ( dat ) + { + if ( dat->m_iDataType == TYPE_COLOR ) + { + color[0] = dat->m_Color[0]; + color[1] = dat->m_Color[1]; + color[2] = dat->m_Color[2]; + color[3] = dat->m_Color[3]; + } + else if ( dat->m_iDataType == TYPE_FLOAT ) + { + color[0] = (unsigned char)dat->m_flValue; + } + else if ( dat->m_iDataType == TYPE_INT ) + { + color[0] = dat->m_iValue; + } + else if ( dat->m_iDataType == TYPE_STRING ) + { + // parse the colors out of the string + float a, b, c, d; + sscanf(dat->m_sValue, "%f %f %f %f", &a, &b, &c, &d); + color[0] = (unsigned char)a; + color[1] = (unsigned char)b; + color[2] = (unsigned char)c; + color[3] = (unsigned char)d; + } + } + return color; +} + +//----------------------------------------------------------------------------- +// Purpose: Sets a color +//----------------------------------------------------------------------------- +void KeyValues::SetColor( const char *keyName, Color value) +{ + KeyValues *dat = FindKey( keyName, true ); + + if ( dat ) + { + dat->m_iDataType = TYPE_COLOR; + dat->m_Color[0] = value[0]; + dat->m_Color[1] = value[1]; + dat->m_Color[2] = value[2]; + dat->m_Color[3] = value[3]; + } +} + +void KeyValues::SetStringValue( char const *strValue ) +{ + if ( m_sValue != NULL ) + { + // delete the old value + delete [] m_sValue; + } + + if ( m_wsValue != NULL ) + { + // make sure we're not storing the WSTRING - as we're converting over to STRING + delete [] m_wsValue; + m_wsValue = NULL; + } + + if (!strValue) + { + // ensure a valid value + strValue = ""; + } + + // allocate memory for the new value and copy it in + int len = Q_strlen( strValue ); + m_sValue = new char[len + 1]; + Q_memcpy( m_sValue, strValue, len+1 ); + + m_iDataType = TYPE_STRING; +} + +//----------------------------------------------------------------------------- +// Purpose: Set the string value of a keyName. +//----------------------------------------------------------------------------- +void KeyValues::SetString( const char *keyName, const char *value ) +{ + KeyValues *dat = FindKey( keyName, true ); + + if ( dat ) + { + if ( dat->m_sValue != NULL ) + { + // delete the old value + delete [] dat->m_sValue; + } + + if ( dat->m_wsValue != NULL ) + { + // make sure we're not storing the WSTRING - as we're converting over to STRING + delete [] dat->m_wsValue; + } + dat->m_wsValue = NULL; + + if (!value) + { + // ensure a valid value + value = ""; + } + + // allocate memory for the new value and copy it in + int len = Q_strlen( value ); + dat->m_sValue = new char[len + 1]; + Q_memcpy( dat->m_sValue, value, len+1 ); + + dat->m_iDataType = TYPE_STRING; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Set the string value of a keyName. +//----------------------------------------------------------------------------- +void KeyValues::SetWString( const char *keyName, const wchar_t *value ) +{ + KeyValues *dat = FindKey( keyName, true ); + if ( dat ) + { + // delete the old value + delete [] dat->m_wsValue; + // make sure we're not storing the STRING - as we're converting over to WSTRING + delete [] dat->m_sValue; + dat->m_sValue = NULL; + + if (!value) + { + // ensure a valid value + value = L""; + } + + // allocate memory for the new value and copy it in + int len = wcslen( value ); + dat->m_wsValue = new wchar_t[len + 1]; + Q_memcpy( dat->m_wsValue, value, (len+1) * sizeof(wchar_t) ); + + dat->m_iDataType = TYPE_WSTRING; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Set the integer value of a keyName. +//----------------------------------------------------------------------------- +void KeyValues::SetInt( const char *keyName, int value ) +{ + KeyValues *dat = FindKey( keyName, true ); + + if ( dat ) + { + dat->m_iValue = value; + dat->m_iDataType = TYPE_INT; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Set the integer value of a keyName. +//----------------------------------------------------------------------------- +void KeyValues::SetUint64( const char *keyName, uint64 value ) +{ + KeyValues *dat = FindKey( keyName, true ); + + if ( dat ) + { + // delete the old value + delete [] dat->m_sValue; + // make sure we're not storing the WSTRING - as we're converting over to STRING + delete [] dat->m_wsValue; + dat->m_wsValue = NULL; + + dat->m_sValue = new char[sizeof(uint64)]; + *((uint64 *)dat->m_sValue) = value; + dat->m_iDataType = TYPE_UINT64; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Set the float value of a keyName. +//----------------------------------------------------------------------------- +void KeyValues::SetFloat( const char *keyName, float value ) +{ + KeyValues *dat = FindKey( keyName, true ); + + if ( dat ) + { + dat->m_flValue = value; + dat->m_iDataType = TYPE_FLOAT; + } +} + +void KeyValues::SetName( const char * setName ) +{ + m_iKeyName = KeyValuesSystem()->GetSymbolForString( setName ); +} + +//----------------------------------------------------------------------------- +// Purpose: Set the pointer value of a keyName. +//----------------------------------------------------------------------------- +void KeyValues::SetPtr( const char *keyName, void *value ) +{ + KeyValues *dat = FindKey( keyName, true ); + + if ( dat ) + { + dat->m_pValue = value; + dat->m_iDataType = TYPE_PTR; + } +} + +void KeyValues::RecursiveCopyKeyValues( KeyValues& src ) +{ + // garymcthack - need to check this code for possible buffer overruns. + + m_iKeyName = src.GetNameSymbol(); + + if( !src.m_pSub ) + { + m_iDataType = src.m_iDataType; + char buf[256]; + switch( src.m_iDataType ) + { + case TYPE_NONE: + break; + case TYPE_STRING: + if( src.m_sValue ) + { + int len = Q_strlen(src.m_sValue) + 1; + m_sValue = new char[len]; + Q_strncpy( m_sValue, src.m_sValue, len ); + } + break; + case TYPE_INT: + { + m_iValue = src.m_iValue; + Q_snprintf( buf,sizeof(buf), "%d", m_iValue ); + int len = Q_strlen(buf) + 1; + m_sValue = new char[len]; + Q_strncpy( m_sValue, buf, len ); + } + break; + case TYPE_FLOAT: + { + m_flValue = src.m_flValue; + Q_snprintf( buf,sizeof(buf), "%f", m_flValue ); + int len = Q_strlen(buf) + 1; + m_sValue = new char[len]; + Q_strncpy( m_sValue, buf, len ); + } + break; + case TYPE_PTR: + { + m_pValue = src.m_pValue; + } + break; + case TYPE_UINT64: + { + m_sValue = new char[sizeof(uint64)]; + Q_memcpy( m_sValue, src.m_sValue, sizeof(uint64) ); + } + break; + case TYPE_COLOR: + { + m_Color[0] = src.m_Color[0]; + m_Color[1] = src.m_Color[1]; + m_Color[2] = src.m_Color[2]; + m_Color[3] = src.m_Color[3]; + } + break; + + default: + { + // do nothing . .what the heck is this? + Assert( 0 ); + } + break; + } + + } +#if 0 + KeyValues *pDst = this; + for ( KeyValues *pSrc = src.m_pSub; pSrc; pSrc = pSrc->m_pPeer ) + { + if ( pSrc->m_pSub ) + { + pDst->m_pSub = new KeyValues( pSrc->m_pSub->getName() ); + pDst->m_pSub->RecursiveCopyKeyValues( *pSrc->m_pSub ); + } + else + { + // copy non-empty keys + if ( pSrc->m_sValue && *(pSrc->m_sValue) ) + { + pDst->m_pPeer = new KeyValues( + } + } + } +#endif + + // Handle the immediate child + if( src.m_pSub ) + { + m_pSub = new KeyValues( NULL ); + m_pSub->RecursiveCopyKeyValues( *src.m_pSub ); + } + + // Handle the immediate peer + if( src.m_pPeer ) + { + m_pPeer = new KeyValues( NULL ); + m_pPeer->RecursiveCopyKeyValues( *src.m_pPeer ); + } +} + +KeyValues& KeyValues::operator=( KeyValues& src ) +{ + RemoveEverything(); + Init(); // reset all values + RecursiveCopyKeyValues( src ); + return *this; +} + + +//----------------------------------------------------------------------------- +// Make a new copy of all subkeys, add them all to the passed-in keyvalues +//----------------------------------------------------------------------------- +void KeyValues::CopySubkeys( KeyValues *pParent ) const +{ + // recursively copy subkeys + // Also maintain ordering.... + KeyValues *pPrev = NULL; + for ( KeyValues *sub = m_pSub; sub != NULL; sub = sub->m_pPeer ) + { + // take a copy of the subkey + KeyValues *dat = sub->MakeCopy(); + + // add into subkey list + if (pPrev) + { + pPrev->m_pPeer = dat; + } + else + { + pParent->m_pSub = dat; + } + dat->m_pPeer = NULL; + pPrev = dat; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Makes a copy of the whole key-value pair set +//----------------------------------------------------------------------------- +KeyValues *KeyValues::MakeCopy( void ) const +{ + KeyValues *newKeyValue = new KeyValues(GetName()); + + // copy data + newKeyValue->m_iDataType = m_iDataType; + switch ( m_iDataType ) + { + case TYPE_STRING: + { + if ( m_sValue ) + { + int len = Q_strlen( m_sValue ); + Assert( !newKeyValue->m_sValue ); + newKeyValue->m_sValue = new char[len + 1]; + Q_memcpy( newKeyValue->m_sValue, m_sValue, len+1 ); + } + } + break; + case TYPE_WSTRING: + { + if ( m_wsValue ) + { + int len = wcslen( m_wsValue ); + newKeyValue->m_wsValue = new wchar_t[len+1]; + Q_memcpy( newKeyValue->m_wsValue, m_wsValue, (len+1)*sizeof(wchar_t)); + } + } + break; + + case TYPE_INT: + newKeyValue->m_iValue = m_iValue; + break; + + case TYPE_FLOAT: + newKeyValue->m_flValue = m_flValue; + break; + + case TYPE_PTR: + newKeyValue->m_pValue = m_pValue; + break; + + case TYPE_COLOR: + newKeyValue->m_Color[0] = m_Color[0]; + newKeyValue->m_Color[1] = m_Color[1]; + newKeyValue->m_Color[2] = m_Color[2]; + newKeyValue->m_Color[3] = m_Color[3]; + break; + + case TYPE_UINT64: + newKeyValue->m_sValue = new char[sizeof(uint64)]; + Q_memcpy( newKeyValue->m_sValue, m_sValue, sizeof(uint64) ); + break; + }; + + // recursively copy subkeys + CopySubkeys( newKeyValue ); + return newKeyValue; +} + + +//----------------------------------------------------------------------------- +// Purpose: Check if a keyName has no value assigned to it. +//----------------------------------------------------------------------------- +bool KeyValues::IsEmpty(const char *keyName) +{ + KeyValues *dat = FindKey(keyName, false); + if (!dat) + return true; + + if (dat->m_iDataType == TYPE_NONE && dat->m_pSub == NULL) + return true; + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: Clear out all subkeys, and the current value +//----------------------------------------------------------------------------- +void KeyValues::Clear( void ) +{ + delete m_pSub; + m_pSub = NULL; + m_iDataType = TYPE_NONE; +} + +//----------------------------------------------------------------------------- +// Purpose: Get the data type of the value stored in a keyName +//----------------------------------------------------------------------------- +KeyValues::types_t KeyValues::GetDataType(const char *keyName) +{ + KeyValues *dat = FindKey(keyName, false); + if (dat) + return (types_t)dat->m_iDataType; + + return TYPE_NONE; +} + +//----------------------------------------------------------------------------- +// Purpose: Deletion, ensures object gets deleted from correct heap +//----------------------------------------------------------------------------- +void KeyValues::deleteThis() +{ + delete this; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : includedKeys - +//----------------------------------------------------------------------------- +void KeyValues::AppendIncludedKeys( CUtlVector< KeyValues * >& includedKeys ) +{ + // Append any included keys, too... + int includeCount = includedKeys.Count(); + int i; + for ( i = 0; i < includeCount; i++ ) + { + KeyValues *kv = includedKeys[ i ]; + Assert( kv ); + + KeyValues *insertSpot = this; + while ( insertSpot->GetNextKey() ) + { + insertSpot = insertSpot->GetNextKey(); + } + + insertSpot->SetNextKey( kv ); + } +} + +void KeyValues::ParseIncludedKeys( char const *resourceName, const char *filetoinclude, + IBaseFileSystem* pFileSystem, const char *pPathID, CUtlVector< KeyValues * >& includedKeys ) +{ + Assert( resourceName ); + Assert( filetoinclude ); + Assert( pFileSystem ); + + // Load it... + if ( !pFileSystem ) + { + return; + } + + // Get relative subdirectory + char fullpath[ 512 ]; + Q_strncpy( fullpath, resourceName, sizeof( fullpath ) ); + + // Strip off characters back to start or first / + bool done = false; + int len = Q_strlen( fullpath ); + while ( !done ) + { + if ( len <= 0 ) + { + break; + } + + if ( fullpath[ len - 1 ] == '\\' || + fullpath[ len - 1 ] == '/' ) + { + break; + } + + // zero it + fullpath[ len - 1 ] = 0; + --len; + } + + // Append included file + Q_strncat( fullpath, filetoinclude, sizeof( fullpath ), COPY_ALL_CHARACTERS ); + + KeyValues *newKV = new KeyValues( fullpath ); + + // CUtlSymbol save = s_CurrentFileSymbol; // did that had any use ??? + + newKV->UsesEscapeSequences( m_bHasEscapeSequences != 0 ); // use same format as parent + + if ( newKV->LoadFromFile( pFileSystem, fullpath, pPathID ) ) + { + includedKeys.AddToTail( newKV ); + } + else + { + DevMsg( "KeyValues::ParseIncludedKeys: Couldn't load included keyvalue file %s\n", fullpath ); + newKV->deleteThis(); + } + + // s_CurrentFileSymbol = save; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : baseKeys - +//----------------------------------------------------------------------------- +void KeyValues::MergeBaseKeys( CUtlVector< KeyValues * >& baseKeys ) +{ + int includeCount = baseKeys.Count(); + int i; + for ( i = 0; i < includeCount; i++ ) + { + KeyValues *kv = baseKeys[ i ]; + Assert( kv ); + + RecursiveMergeKeyValues( kv ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : baseKV - keyvalues we're basing ourselves on +//----------------------------------------------------------------------------- +void KeyValues::RecursiveMergeKeyValues( KeyValues *baseKV ) +{ + // Merge ourselves + // we always want to keep our value, so nothing to do here + + // Now merge our children + for ( KeyValues *baseChild = baseKV->m_pSub; baseChild != NULL; baseChild = baseChild->m_pPeer ) + { + // for each child in base, see if we have a matching kv + + bool bFoundMatch = false; + + // If we have a child by the same name, merge those keys + for ( KeyValues *newChild = m_pSub; newChild != NULL; newChild = newChild->m_pPeer ) + { + if ( !Q_strcmp( baseChild->GetName(), newChild->GetName() ) ) + { + newChild->RecursiveMergeKeyValues( baseChild ); + bFoundMatch = true; + break; + } + } + + // If not merged, append this key + if ( !bFoundMatch ) + { + KeyValues *dat = baseChild->MakeCopy(); + Assert( dat ); + AddSubKey( dat ); + } + } +} + +//----------------------------------------------------------------------------- +// Returns whether a keyvalues conditional evaluates to true or false +// Needs more flexibility with conditionals, checking convars would be nice. +//----------------------------------------------------------------------------- +bool EvaluateConditional( const char *str ) +{ + bool bResult = false; + bool bXboxUI = IsX360(); + + if ( bXboxUI ) + { + bResult = !Q_stricmp( "[$X360]", str ); + } + else + { + bResult = !Q_stricmp( "[$WIN32]", str ); + } + + return bResult; +} + + +//----------------------------------------------------------------------------- +// Read from a buffer... +//----------------------------------------------------------------------------- +bool KeyValues::LoadFromBuffer( char const *resourceName, CUtlBuffer &buf, IBaseFileSystem* pFileSystem, const char *pPathID ) +{ + KeyValues *pPreviousKey = NULL; + KeyValues *pCurrentKey = this; + CUtlVector< KeyValues * > includedKeys; + CUtlVector< KeyValues * > baseKeys; + bool wasQuoted; + bool wasConditional; + g_KeyValuesErrorStack.SetFilename( resourceName ); + do + { + bool bAccepted = true; + + // the first thing must be a key + const char *s = ReadToken( buf, wasQuoted, wasConditional ); + if ( !buf.IsValid() || !s || *s == 0 ) + break; + + if ( !Q_stricmp( s, "#include" ) ) // special include macro (not a key name) + { + s = ReadToken( buf, wasQuoted, wasConditional ); + // Name of subfile to load is now in s + + if ( !s || *s == 0 ) + { + g_KeyValuesErrorStack.ReportError("#include is NULL " ); + } + else + { + ParseIncludedKeys( resourceName, s, pFileSystem, pPathID, includedKeys ); + } + + continue; + } + else if ( !Q_stricmp( s, "#base" ) ) + { + s = ReadToken( buf, wasQuoted, wasConditional ); + // Name of subfile to load is now in s + + if ( !s || *s == 0 ) + { + g_KeyValuesErrorStack.ReportError("#base is NULL " ); + } + else + { + ParseIncludedKeys( resourceName, s, pFileSystem, pPathID, baseKeys ); + } + + continue; + } + + if ( !pCurrentKey ) + { + pCurrentKey = new KeyValues( s ); + Assert( pCurrentKey ); + + pCurrentKey->UsesEscapeSequences( m_bHasEscapeSequences != 0 ); // same format has parent use + + if ( pPreviousKey ) + { + pPreviousKey->SetNextKey( pCurrentKey ); + } + } + else + { + pCurrentKey->SetName( s ); + } + + // get the '{' + s = ReadToken( buf, wasQuoted, wasConditional ); + + if ( wasConditional ) + { + bAccepted = EvaluateConditional( s ); + + // Now get the '{' + s = ReadToken( buf, wasQuoted, wasConditional ); + } + + if ( s && *s == '{' && !wasQuoted ) + { + // header is valid so load the file + pCurrentKey->RecursiveLoadFromBuffer( resourceName, buf ); + } + else + { + g_KeyValuesErrorStack.ReportError("LoadFromBuffer: missing {" ); + } + + if ( !bAccepted ) + { + if ( pPreviousKey ) + { + pPreviousKey->SetNextKey( NULL ); + } + pCurrentKey->Clear(); + } + else + { + pPreviousKey = pCurrentKey; + pCurrentKey = NULL; + } + } while ( buf.IsValid() ); + + AppendIncludedKeys( includedKeys ); + { + // delete included keys! + int i; + for ( i = includedKeys.Count() - 1; i > 0; i-- ) + { + KeyValues *kv = includedKeys[ i ]; + kv->deleteThis(); + } + } + + MergeBaseKeys( baseKeys ); + { + // delete base keys! + int i; + for ( i = baseKeys.Count() - 1; i >= 0; i-- ) + { + KeyValues *kv = baseKeys[ i ]; + kv->deleteThis(); + } + } + + g_KeyValuesErrorStack.SetFilename( "" ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Read from a buffer... +//----------------------------------------------------------------------------- +bool KeyValues::LoadFromBuffer( char const *resourceName, const char *pBuffer, IBaseFileSystem* pFileSystem, const char *pPathID ) +{ + if ( !pBuffer ) + return true; + + int nLen = Q_strlen( pBuffer ); + CUtlBuffer buf( pBuffer, nLen, CUtlBuffer::READ_ONLY | CUtlBuffer::TEXT_BUFFER ); + return LoadFromBuffer( resourceName, buf, pFileSystem, pPathID ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void KeyValues::RecursiveLoadFromBuffer( char const *resourceName, CUtlBuffer &buf ) +{ + CKeyErrorContext errorReport(this); + bool wasQuoted; + bool wasConditional; + // keep this out of the stack until a key is parsed + CKeyErrorContext errorKey( INVALID_KEY_SYMBOL ); + while ( 1 ) + { + bool bAccepted = true; + + // get the key name + const char * name = ReadToken( buf, wasQuoted, wasConditional ); + + if ( !name ) // EOF stop reading + { + g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got EOF instead of keyname" ); + break; + } + + if ( !*name ) // empty token, maybe "" or EOF + { + g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got empty keyname" ); + break; + } + + if ( *name == '}' && !wasQuoted ) // top level closed, stop reading + break; + + // Always create the key; note that this could potentially + // cause some duplication, but that's what we want sometimes + KeyValues *dat = CreateKey( name ); + + errorKey.Reset( dat->GetNameSymbol() ); + + // get the value + const char * value = ReadToken( buf, wasQuoted, wasConditional ); + + if ( wasConditional && value ) + { + bAccepted = EvaluateConditional( value ); + + // get the real value + value = ReadToken( buf, wasQuoted, wasConditional ); + } + + if ( !value ) + { + g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got NULL key" ); + break; + } + + if ( *value == '}' && !wasQuoted ) + { + g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got } in key" ); + break; + } + + if ( *value == '{' && !wasQuoted ) + { + // this isn't a key, it's a section + errorKey.Reset( INVALID_KEY_SYMBOL ); + // sub value list + dat->RecursiveLoadFromBuffer( resourceName, buf ); + } + else + { + if ( wasConditional ) + { + g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got conditional between key and value" ); + break; + } + + if (dat->m_sValue) + { + delete[] dat->m_sValue; + dat->m_sValue = NULL; + } + + int len = Q_strlen( value ); + + // Here, let's determine if we got a float or an int.... + char* pIEnd; // pos where int scan ended + char* pFEnd; // pos where float scan ended + const char* pSEnd = value + len ; // pos where token ends + + int ival = strtol( value, &pIEnd, 10 ); + float fval = (float)strtod( value, &pFEnd ); + + if ( *value == 0 ) + { + dat->m_iDataType = TYPE_STRING; + } + else if ( ( 18 == len ) && ( value[0] == '0' ) && ( value[1] == 'x' ) ) + { + // an 18-byte value prefixed with "0x" (followed by 16 hex digits) is an int64 value + int64 retVal = 0; + for( int i=2; i < 2 + 16; i++ ) + { + char digit = value[i]; + if ( digit >= 'a' ) + digit -= 'a' - ( '9' + 1 ); + else + if ( digit >= 'A' ) + digit -= 'A' - ( '9' + 1 ); + retVal = ( retVal * 16 ) + ( digit - '0' ); + } + dat->m_sValue = new char[sizeof(uint64)]; + *((uint64 *)dat->m_sValue) = retVal; + dat->m_iDataType = TYPE_UINT64; + } + else if ( (pFEnd > pIEnd) && (pFEnd == pSEnd) ) + { + dat->m_flValue = fval; + dat->m_iDataType = TYPE_FLOAT; + } + else if (pIEnd == pSEnd) + { + dat->m_iValue = ival; + dat->m_iDataType = TYPE_INT; + } + else + { + dat->m_iDataType = TYPE_STRING; + } + + if (dat->m_iDataType == TYPE_STRING) + { + // copy in the string information + dat->m_sValue = new char[len+1]; + Q_memcpy( dat->m_sValue, value, len+1 ); + } + + // Look ahead one token for a conditional tag + int prevPos = buf.TellGet(); + const char *peek = ReadToken( buf, wasQuoted, wasConditional ); + if ( wasConditional ) + { + bAccepted = EvaluateConditional( peek ); + } + else + { + buf.SeekGet( CUtlBuffer::SEEK_HEAD, prevPos ); + } + } + + if ( !bAccepted ) + { + this->RemoveSubKey( dat ); + dat->deleteThis(); + dat = NULL; + } + } +} + + + +// writes KeyValue as binary data to buffer +bool KeyValues::WriteAsBinary( CUtlBuffer &buffer ) +{ + if ( buffer.IsText() ) // must be a binary buffer + return false; + + if ( !buffer.IsValid() ) // must be valid, no overflows etc + return false; + + // Write subkeys: + + // loop through all our peers + for ( KeyValues *dat = this; dat != NULL; dat = dat->m_pPeer ) + { + // write type + buffer.PutUnsignedChar( dat->m_iDataType ); + + // write name + buffer.PutString( dat->GetName() ); + + // write type + switch (dat->m_iDataType) + { + case TYPE_NONE: + { + dat->m_pSub->WriteAsBinary( buffer ); + break; + } + case TYPE_STRING: + { + if (dat->m_sValue && *(dat->m_sValue)) + { + buffer.PutString( dat->m_sValue ); + } + else + { + buffer.PutString( "" ); + } + break; + } + case TYPE_WSTRING: + { + Assert( !"TYPE_WSTRING" ); + break; + } + + case TYPE_INT: + { + buffer.PutInt( dat->m_iValue ); + break; + } + + case TYPE_UINT64: + { + buffer.PutDouble( *((double *)dat->m_sValue) ); + break; + } + + case TYPE_FLOAT: + { + buffer.PutFloat( dat->m_flValue ); + break; + } + case TYPE_COLOR: + { + buffer.PutUnsignedChar( dat->m_Color[0] ); + buffer.PutUnsignedChar( dat->m_Color[1] ); + buffer.PutUnsignedChar( dat->m_Color[2] ); + buffer.PutUnsignedChar( dat->m_Color[3] ); + break; + } + case TYPE_PTR: + { + buffer.PutUnsignedInt( (int)dat->m_pValue ); + } + + default: + break; + } + } + + // write tail, marks end of peers + buffer.PutUnsignedChar( TYPE_NUMTYPES ); + + return buffer.IsValid(); +} + +// read KeyValues from binary buffer, returns true if parsing was successful +bool KeyValues::ReadAsBinary( CUtlBuffer &buffer ) +{ + if ( buffer.IsText() ) // must be a binary buffer + return false; + + if ( !buffer.IsValid() ) // must be valid, no overflows etc + return false; + + RemoveEverything(); // remove current content + Init(); // reset + + char token[KEYVALUES_TOKEN_SIZE]; + KeyValues *dat = this; + types_t type = (types_t)buffer.GetUnsignedChar(); + + // loop through all our peers + while ( true ) + { + if ( type == TYPE_NUMTYPES ) + break; // no more peers + + dat->m_iDataType = type; + + buffer.GetString( token, KEYVALUES_TOKEN_SIZE-1 ); + token[KEYVALUES_TOKEN_SIZE-1] = 0; + + dat->SetName( token ); + + switch ( type ) + { + case TYPE_NONE: + { + dat->m_pSub = new KeyValues(""); + dat->m_pSub->ReadAsBinary( buffer ); + break; + } + case TYPE_STRING: + { + buffer.GetString( token, KEYVALUES_TOKEN_SIZE-1 ); + token[KEYVALUES_TOKEN_SIZE-1] = 0; + + int len = Q_strlen( token ); + dat->m_sValue = new char[len + 1]; + Q_memcpy( dat->m_sValue, token, len+1 ); + + break; + } + case TYPE_WSTRING: + { + Assert( !"TYPE_WSTRING" ); + break; + } + + case TYPE_INT: + { + dat->m_iValue = buffer.GetInt(); + break; + } + + case TYPE_UINT64: + { + dat->m_sValue = new char[sizeof(uint64)]; + *((double *)dat->m_sValue) = buffer.GetDouble(); + } + + case TYPE_FLOAT: + { + dat->m_flValue = buffer.GetFloat(); + break; + } + case TYPE_COLOR: + { + dat->m_Color[0] = buffer.GetUnsignedChar(); + dat->m_Color[1] = buffer.GetUnsignedChar(); + dat->m_Color[2] = buffer.GetUnsignedChar(); + dat->m_Color[3] = buffer.GetUnsignedChar(); + break; + } + case TYPE_PTR: + { + dat->m_pValue = (void*)buffer.GetUnsignedInt(); + } + + default: + break; + } + + if ( !buffer.IsValid() ) // error occured + return false; + + type = (types_t)buffer.GetUnsignedChar(); + + if ( type == TYPE_NUMTYPES ) + break; + + // new peer follows + dat->m_pPeer = new KeyValues(""); + dat = dat->m_pPeer; + } + + return buffer.IsValid(); +} + +#include "tier0/memdbgoff.h" + +//----------------------------------------------------------------------------- +// Purpose: memory allocator +//----------------------------------------------------------------------------- +void *KeyValues::operator new( size_t iAllocSize ) +{ + MEM_ALLOC_CREDIT(); + return KeyValuesSystem()->AllocKeyValuesMemory(iAllocSize); +} + +void *KeyValues::operator new( size_t iAllocSize, int nBlockUse, const char *pFileName, int nLine ) +{ +#ifndef NO_MALLOC_OVERRIDE + MemAlloc_PushAllocDbgInfo( pFileName, nLine ); +#endif + void *p = KeyValuesSystem()->AllocKeyValuesMemory(iAllocSize); +#ifndef NO_MALLOC_OVERRIDE + MemAlloc_PopAllocDbgInfo(); +#endif + return p; +} + +//----------------------------------------------------------------------------- +// Purpose: deallocator +//----------------------------------------------------------------------------- +void KeyValues::operator delete( void *pMem ) +{ + KeyValuesSystem()->FreeKeyValuesMemory(pMem); +} + +void KeyValues::operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine ) +{ + KeyValuesSystem()->FreeKeyValuesMemory(pMem); +} + +void KeyValues::UnpackIntoStructure( KeyValuesUnpackStructure const *pUnpackTable, void *pDest ) +{ + uint8 *dest=(uint8 *) pDest; + while( pUnpackTable->m_pKeyName ) + { + uint8 *dest_field=dest+pUnpackTable->m_nFieldOffset; + KeyValues *find_it=FindKey( pUnpackTable->m_pKeyName ); + switch( pUnpackTable->m_eDataType ) + { + case UNPACK_TYPE_FLOAT: + { + float default_value=(pUnpackTable->m_pKeyDefault)?atof(pUnpackTable->m_pKeyDefault):0.0; + *( ( float *) dest_field)=GetFloat( pUnpackTable->m_pKeyName, default_value ); + break; + } + break; + + case UNPACK_TYPE_VECTOR: + { + Vector *dest_v=(Vector *) dest_field; + char const *src_string= + GetString( pUnpackTable->m_pKeyName, pUnpackTable->m_pKeyDefault ); + if ( (!src_string) || + ( sscanf(src_string,"%f %f %f", + &(dest_v->x), &(dest_v->y), &(dest_v->z)) != 3)) + dest_v->Init( 0, 0, 0 ); + } + break; + + case UNPACK_TYPE_FOUR_FLOATS: + { + float *dest_f=(float *) dest_field; + char const *src_string= + GetString( pUnpackTable->m_pKeyName, pUnpackTable->m_pKeyDefault ); + if ( (!src_string) || + ( sscanf(src_string,"%f %f %f %f", + dest_f,dest_f+1,dest_f+2,dest_f+3)) != 4) + memset( dest_f, 0, 4*sizeof(float) ); + } + break; + + case UNPACK_TYPE_TWO_FLOATS: + { + float *dest_f=(float *) dest_field; + char const *src_string= + GetString( pUnpackTable->m_pKeyName, pUnpackTable->m_pKeyDefault ); + if ( (!src_string) || + ( sscanf(src_string,"%f %f", + dest_f,dest_f+1)) != 2) + memset( dest_f, 0, 2*sizeof(float) ); + } + break; + + case UNPACK_TYPE_STRING: + { + char *dest_s=(char *) dest_field; + strncpy( dest_s, GetString( pUnpackTable->m_pKeyName, + pUnpackTable->m_pKeyDefault ), + pUnpackTable->m_nFieldSize ); + + } + break; + + case UNPACK_TYPE_INT: + { + int *dest_i=(int *) dest_field; + int default_int=0; + if ( pUnpackTable->m_pKeyDefault) + default_int = atoi( pUnpackTable->m_pKeyDefault ); + *(dest_i)=GetInt( pUnpackTable->m_pKeyName, default_int ); + } + break; + + case UNPACK_TYPE_VECTOR_COLOR: + { + Vector *dest_v=(Vector *) dest_field; + if (find_it) + { + Color c=GetColor( pUnpackTable->m_pKeyName ); + dest_v->x = c.r(); + dest_v->y = c.g(); + dest_v->z = c.b(); + } + else + { + if ( pUnpackTable->m_pKeyDefault ) + sscanf(pUnpackTable->m_pKeyDefault,"%f %f %f", + &(dest_v->x), &(dest_v->y), &(dest_v->z)); + else + dest_v->Init( 0, 0, 0 ); + } + *(dest_v) *= (1.0/255); + } + } + pUnpackTable++; + } +} + +//----------------------------------------------------------------------------- +// Helper function for processing a keyvalue tree for console resolution support. +// Alters key/values for easier console video resolution support. +// If running SD (640x480), the presence of "???_lodef" creates or slams "???". +// If running HD (1280x720), the presence of "???_hidef" creates or slams "???". +//----------------------------------------------------------------------------- +bool KeyValues::ProcessResolutionKeys( const char *pResString ) +{ + if ( !pResString ) + { + // not for pc, console only + return false; + } + + KeyValues *pSubKey = GetFirstSubKey(); + if ( !pSubKey ) + { + // not a block + return false; + } + + for ( ; pSubKey != NULL; pSubKey = pSubKey->GetNextKey() ) + { + // recursively descend each sub block + pSubKey->ProcessResolutionKeys( pResString ); + + // check to see if our substring is present + if ( Q_stristr( pSubKey->GetName(), pResString ) != NULL ) + { + char normalKeyName[128]; + V_strncpy( normalKeyName, pSubKey->GetName(), sizeof( normalKeyName ) ); + + // substring must match exactly, otherwise keys like "_lodef" and "_lodef_wide" would clash. + char *pString = Q_stristr( normalKeyName, pResString ); + if ( pString && !Q_stricmp( pString, pResString ) ) + { + *pString = '\0'; + + // find and delete the original key (if any) + KeyValues *pKey = FindKey( normalKeyName ); + if ( pKey ) + { + // remove the key + RemoveSubKey( pKey ); + } + + // rename the marked key + pSubKey->SetName( normalKeyName ); + } + } + } + + return true; +} \ No newline at end of file diff --git a/tier1/NetAdr.cpp b/tier1/NetAdr.cpp new file mode 100644 index 00000000..ac9ebba5 --- /dev/null +++ b/tier1/NetAdr.cpp @@ -0,0 +1,331 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// NetAdr.cpp: implementation of the CNetAdr class. +// +//===========================================================================// +#if defined( _WIN32 ) && !defined( _X360 ) +#include +#endif + +#include "tier0/dbg.h" +#include "netadr.h" +#include "tier1/strtools.h" + +#if defined( _WIN32 ) && !defined( _X360 ) +#define WIN32_LEAN_AND_MEAN +#include +typedef int socklen_t; +#elif !defined( _X360 ) +#include // ntohs() +#include // gethostbyname() +#include // getsockname() +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +bool netadr_t::CompareAdr (const netadr_t &a, bool onlyBase) const +{ + if ( a.type != type ) + return false; + + if ( type == NA_LOOPBACK ) + return true; + + if ( type == NA_BROADCAST ) + return true; + + if ( type == NA_IP ) + { + if ( !onlyBase && (port != a.port) ) + return false; + + if ( a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2] && a.ip[3] == ip[3] ) + return true; + } + + return false; +} + +bool netadr_t::CompareClassBAdr (const netadr_t &a) const +{ + if ( a.type != type ) + return false; + + if ( type == NA_LOOPBACK ) + return true; + + if ( type == NA_IP ) + { + if (a.ip[0] == ip[0] && a.ip[1] == ip[1] ) + return true; + } + + return false; +} + +bool netadr_t::CompareClassCAdr (const netadr_t &a) const +{ + if ( a.type != type ) + return false; + + if ( type == NA_LOOPBACK ) + return true; + + if ( type == NA_IP ) + { + if (a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2] ) + return true; + } + + return false; +} +// reserved addresses are not routeable, so they can all be used in a LAN game +bool netadr_t::IsReservedAdr () const +{ + if ( type == NA_LOOPBACK ) + return true; + + if ( type == NA_IP ) + { + if ( (ip[0] == 10) || // 10.x.x.x is reserved + (ip[0] == 127) || // 127.x.x.x + (ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) || // 172.16.x.x - 172.31.x.x + (ip[0] == 192 && ip[1] >= 168) ) // 192.168.x.x + return true; + } + return false; +} + +const char * netadr_t::ToString(bool baseOnly) const +{ + static char s[64]; + + Q_strncpy (s, "unknown", sizeof( s ) ); + + if (type == NA_LOOPBACK) + { + Q_strncpy (s, "loopback", sizeof( s ) ); + } + else if (type == NA_BROADCAST) + { + Q_strncpy (s, "broadcast", sizeof( s ) ); + } + else if (type == NA_IP) + { + if ( baseOnly) + { + Q_snprintf (s, sizeof( s ), "%i.%i.%i.%i", ip[0], ip[1], ip[2], ip[3]); + } + else + { + Q_snprintf (s, sizeof( s ), "%i.%i.%i.%i:%i", ip[0], ip[1], ip[2], ip[3], ntohs(port)); + } + } + + return s; +} + +bool netadr_t::IsLocalhost() const +{ + // are we 127.0.0.1 ? + return (ip[0] == 127) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 1); +} + +bool netadr_t::IsLoopback() const +{ + // are we useding engine loopback buffers + return type == NA_LOOPBACK; +} + +void netadr_t::Clear() +{ + ip[0] = ip[1] = ip[2] = ip[3] = 0; + port = 0; + type = NA_NULL; +} + +void netadr_t::SetIP(uint8 b1, uint8 b2, uint8 b3, uint8 b4) +{ + ip[0] = b1; + ip[1] = b2; + ip[2] = b3; + ip[3] = b4; +} + +void netadr_t::SetIP(uint unIP) +{ + *((uint*)ip) = BigLong( unIP ); +} + +void netadr_t::SetType(netadrtype_t newtype) +{ + type = newtype; +} + +netadrtype_t netadr_t::GetType() const +{ + return type; +} + +unsigned short netadr_t::GetPort() const +{ + return BigShort( port ); +} + +unsigned int netadr_t::GetIP() const +{ + return *(unsigned int *)&ip;; +} + +unsigned long netadr_t::addr_ntohl() const +{ + return ntohl( GetIP() ); +} + +unsigned long netadr_t::addr_htonl() const +{ + return htonl( GetIP() ); +} + + +void netadr_t::ToSockadr (struct sockaddr * s) const +{ + Q_memset ( s, 0, sizeof(struct sockaddr)); + + if (type == NA_BROADCAST) + { + ((struct sockaddr_in*)s)->sin_family = AF_INET; + ((struct sockaddr_in*)s)->sin_port = port; + ((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_BROADCAST; + } + else if (type == NA_IP) + { + ((struct sockaddr_in*)s)->sin_family = AF_INET; + ((struct sockaddr_in*)s)->sin_addr.s_addr = *(int *)&ip; + ((struct sockaddr_in*)s)->sin_port = port; + } + else if (type == NA_LOOPBACK ) + { + ((struct sockaddr_in*)s)->sin_family = AF_INET; + ((struct sockaddr_in*)s)->sin_port = port; + ((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_LOOPBACK ; + } +} + +bool netadr_t::SetFromSockadr(const struct sockaddr * s) +{ + if (s->sa_family == AF_INET) + { + type = NA_IP; + *(int *)&ip = ((struct sockaddr_in *)s)->sin_addr.s_addr; + port = ((struct sockaddr_in *)s)->sin_port; + return true; + } + else + { + Clear(); + return false; + } +} + +bool netadr_t::IsValid() const +{ + return ( (port !=0 ) && (type != NA_NULL) && + ( ip[0] != 0 || ip[1] != 0 || ip[2] != 0 || ip[3] != 0 ) ); +} + +#ifdef _WIN32 +#undef SetPort // get around stupid WINSPOOL.H macro +#endif + +void netadr_t::SetPort(unsigned short newport) +{ + port = BigShort( newport ); +} + +void netadr_t::SetFromString( const char *pch, bool bUseDNS ) +{ + Clear(); + type = NA_IP; + + Assert( pch ); // invalid to call this with NULL pointer; fix your code bug! + if ( !pch ) // but let's not crash + return; + + + if ( pch[0] >= '0' && pch[0] <= '9' && strchr( pch, '.' ) ) + { + int n1, n2, n3, n4, n5; + int nRes = sscanf( pch, "%d.%d.%d.%d:%d", &n1, &n2, &n3, &n4, &n5 ); + if ( nRes >= 4 ) + { + SetIP( n1, n2, n3, n4 ); + } + + if ( nRes == 5 ) + { + SetPort( ( uint16 ) n5 ); + } + } + else if ( bUseDNS ) + { +// X360TBD: +#if !defined( _X360 ) + char szHostName[ 256 ]; + Q_strncpy( szHostName, pch, sizeof(szHostName) ); + char *pchColon = strchr( szHostName, ':' ); + if ( pchColon ) + { + *pchColon = 0; + } + + // DNS it + struct hostent *h = gethostbyname( szHostName ); + if ( !h ) + return; + + SetIP( ntohl( *(int *)h->h_addr_list[0] ) ); + + if ( pchColon ) + { + SetPort( atoi( ++pchColon ) ); + } +#else + Assert( 0 ); +#endif + } +} + +bool netadr_t::operator<(const netadr_t &netadr) const +{ + if ( *((uint *)netadr.ip) < *((uint *)ip) ) + return true; + else if ( *((uint *)netadr.ip) > *((uint *)ip) ) + return false; + return ( netadr.port < port ); +} + + +void netadr_t::SetFromSocket( int hSocket ) +{ +#if !defined(_X360) + Clear(); + type = NA_IP; + + struct sockaddr address; + int namelen = sizeof(address); + if ( getsockname( hSocket, (struct sockaddr *)&address, (socklen_t *)&namelen) == 0 ) + { + SetFromSockadr( &address ); + } +#else + Assert(0); +#endif +} diff --git a/tier1/bitbuf.cpp b/tier1/bitbuf.cpp new file mode 100644 index 00000000..f2d72407 --- /dev/null +++ b/tier1/bitbuf.cpp @@ -0,0 +1,1269 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include "bitbuf.h" +#include "coordsize.h" +#include "mathlib/vector.h" +#include "mathlib/mathlib.h" +#include "tier1/strtools.h" +#include "bitvec.h" + +// FIXME: Can't use this until we get multithreaded allocations in tier0 working for tools +// This is used by VVIS and fails to link +// NOTE: This must be the last file included!!! +//#include "tier0/memdbgon.h" + +#ifdef _X360 +// mandatory ... wary of above comment and isolating, tier0 is built as MT though +#include "tier0/memdbgon.h" +#endif + +#if _WIN32 +#define FAST_BIT_SCAN 1 +#if _X360 +#define CountLeadingZeros(x) _CountLeadingZeros(x) +inline unsigned int CountTrailingZeros( unsigned int elem ) +{ + // this implements CountTrailingZeros() / BitScanForward() + unsigned int mask = elem-1; + unsigned int comp = ~elem; + elem = mask & comp; + return (32 - _CountLeadingZeros(elem)); +} +#else +#include +#pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanForward) + +inline unsigned int CountLeadingZeros(unsigned int x) +{ + unsigned long firstBit; + if ( _BitScanReverse(&firstBit,x) ) + return 31 - firstBit; + return 32; +} +inline unsigned int CountTrailingZeros(unsigned int elem) +{ + unsigned long out; + if ( _BitScanForward(&out, elem) ) + return out; + return 32; +} + +#endif +#else +#define FAST_BIT_SCAN 0 +#endif + + +static BitBufErrorHandler g_BitBufErrorHandler = 0; + +inline int BitForBitnum(int bitnum) +{ + return GetBitForBitnum(bitnum); +} + +void InternalBitBufErrorHandler( BitBufErrorType errorType, const char *pDebugName ) +{ + if ( g_BitBufErrorHandler ) + g_BitBufErrorHandler( errorType, pDebugName ); +} + + +void SetBitBufErrorHandler( BitBufErrorHandler fn ) +{ + g_BitBufErrorHandler = fn; +} + + +// #define BB_PROFILING + + +// Precalculated bit masks for WriteUBitLong. Using these tables instead of +// doing the calculations gives a 33% speedup in WriteUBitLong. +unsigned long g_BitWriteMasks[32][33]; + +// (1 << i) - 1 +unsigned long g_ExtraMasks[32]; + +class CBitWriteMasksInit +{ +public: + CBitWriteMasksInit() + { + for( unsigned int startbit=0; startbit < 32; startbit++ ) + { + for( unsigned int nBitsLeft=0; nBitsLeft < 33; nBitsLeft++ ) + { + unsigned int endbit = startbit + nBitsLeft; + g_BitWriteMasks[startbit][nBitsLeft] = BitForBitnum(startbit) - 1; + if(endbit < 32) + g_BitWriteMasks[startbit][nBitsLeft] |= ~(BitForBitnum(endbit) - 1); + } + } + + for ( unsigned int maskBit=0; maskBit < 32; maskBit++ ) + g_ExtraMasks[maskBit] = BitForBitnum(maskBit) - 1; + } +}; +CBitWriteMasksInit g_BitWriteMasksInit; + + +// ---------------------------------------------------------------------------------------- // +// old_bf_write +// ---------------------------------------------------------------------------------------- // + +old_bf_write::old_bf_write() +{ + m_pData = NULL; + m_nDataBytes = 0; + m_nDataBits = -1; // set to -1 so we generate overflow on any operation + m_iCurBit = 0; + m_bOverflow = false; + m_bAssertOnOverflow = true; + m_pDebugName = NULL; +} + +old_bf_write::old_bf_write( const char *pDebugName, void *pData, int nBytes, int nBits ) +{ + m_bAssertOnOverflow = true; + m_pDebugName = pDebugName; + StartWriting( pData, nBytes, 0, nBits ); +} + +old_bf_write::old_bf_write( void *pData, int nBytes, int nBits ) +{ + m_bAssertOnOverflow = true; + m_pDebugName = NULL; + StartWriting( pData, nBytes, 0, nBits ); +} + +void old_bf_write::StartWriting( void *pData, int nBytes, int iStartBit, int nBits ) +{ + // Make sure it's dword aligned and padded. + Assert( (nBytes % 4) == 0 ); + Assert(((unsigned long)pData & 3) == 0); + + // The writing code will overrun the end of the buffer if it isn't dword aligned, so truncate to force alignment + nBytes &= ~3; + + m_pData = (unsigned char*)pData; + m_nDataBytes = nBytes; + + if ( nBits == -1 ) + { + m_nDataBits = nBytes << 3; + } + else + { + Assert( nBits <= nBytes*8 ); + m_nDataBits = nBits; + } + + m_iCurBit = iStartBit; + m_bOverflow = false; +} + +void old_bf_write::Reset() +{ + m_iCurBit = 0; + m_bOverflow = false; +} + + +void old_bf_write::SetAssertOnOverflow( bool bAssert ) +{ + m_bAssertOnOverflow = bAssert; +} + + +const char* old_bf_write::GetDebugName() +{ + return m_pDebugName; +} + + +void old_bf_write::SetDebugName( const char *pDebugName ) +{ + m_pDebugName = pDebugName; +} + + +void old_bf_write::SeekToBit( int bitPos ) +{ + m_iCurBit = bitPos; +} + + +// Sign bit comes first +void old_bf_write::WriteSBitLong( int data, int numbits ) +{ + // Do we have a valid # of bits to encode with? + Assert( numbits >= 1 ); + + // Note: it does this wierdness here so it's bit-compatible with regular integer data in the buffer. + // (Some old code writes direct integers right into the buffer). + if(data < 0) + { +#ifdef _DEBUG + if( numbits < 32 ) + { + // Make sure it doesn't overflow. + + if( data < 0 ) + { + Assert( data >= -(BitForBitnum(numbits-1)) ); + } + else + { + Assert( data < (BitForBitnum(numbits-1)) ); + } + } +#endif + + WriteUBitLong( (unsigned int)(0x80000000 + data), numbits - 1, false ); + WriteOneBit( 1 ); + } + else + { + WriteUBitLong((unsigned int)data, numbits - 1); + WriteOneBit( 0 ); + } +} + +#if _WIN32 +inline unsigned int BitCountNeededToEncode(unsigned int data) +{ +#if defined(_X360) + return (32 - CountLeadingZeros(data+1)) - 1; +#else + unsigned long firstBit; + _BitScanReverse(&firstBit,data+1); + return firstBit; +#endif +} +#endif // _WIN32 + +// writes an unsigned integer with variable bit length +void old_bf_write::WriteUBitVar( unsigned int data ) +{ + if ( ( data &0xf ) == data ) + { + WriteUBitLong( 0, 2 ); + WriteUBitLong( data, 4 ); + } + else + { + if ( ( data & 0xff ) == data ) + { + WriteUBitLong( 1, 2 ); + WriteUBitLong( data, 8 ); + } + else + { + if ( ( data & 0xfff ) == data ) + { + WriteUBitLong( 2, 2 ); + WriteUBitLong( data, 12 ); + } + else + { + WriteUBitLong( 0x3, 2 ); + WriteUBitLong( data, 32 ); + } + } + } +#if 0 +#if !FAST_BIT_SCAN + unsigned int bits = 0; + unsigned int base = 0; + + while (data > (base<<1)) + { + bits++; + base = BitForBitnum(bits)-1; + } +#else + unsigned int bits = BitCountNeededToEncode(data); + unsigned int base = GetBitForBitnum(bits)-1; +#endif + + // how many bits do we use + WriteUBitLong( 0, bits ); + + // end marker + WriteOneBit( 1 ); + + // write the value + if ( bits > 0) + WriteUBitLong( data - base , bits ); +#endif +} + +void old_bf_write::WriteBitLong(unsigned int data, int numbits, bool bSigned) +{ + if(bSigned) + WriteSBitLong((int)data, numbits); + else + WriteUBitLong(data, numbits); +} + +bool old_bf_write::WriteBits(const void *pInData, int nBits) +{ +#if defined( BB_PROFILING ) + VPROF( "old_bf_write::WriteBits" ); +#endif + + unsigned char *pOut = (unsigned char*)pInData; + int nBitsLeft = nBits; + + // Bounds checking.. + if ( (m_iCurBit+nBits) > m_nDataBits ) + { + SetOverflowFlag(); + CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() ); + return false; + } + + // Align output to dword boundary + while (((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8) + { + + WriteUBitLong( *pOut, 8, false ); + ++pOut; + nBitsLeft -= 8; + } + + if ( IsPC() && (nBitsLeft >= 32) && (m_iCurBit & 7) == 0 ) + { + // current bit is byte aligned, do block copy + int numbytes = nBitsLeft >> 3; + int numbits = numbytes << 3; + + Q_memcpy( m_pData+(m_iCurBit>>3), pOut, numbytes ); + pOut += numbytes; + nBitsLeft -= numbits; + m_iCurBit += numbits; + } + + // X360TBD: Can't write dwords in WriteBits because they'll get swapped + if ( IsPC() && nBitsLeft >= 32 ) + { + unsigned long iBitsRight = (m_iCurBit & 31); + unsigned long iBitsLeft = 32 - iBitsRight; + unsigned long bitMaskLeft = g_BitWriteMasks[iBitsRight][32]; + unsigned long bitMaskRight = g_BitWriteMasks[0][iBitsRight]; + + unsigned long *pData = &((unsigned long*)m_pData)[m_iCurBit>>5]; + + // Read dwords. + while(nBitsLeft >= 32) + { + unsigned long curData = *(unsigned long*)pOut; + pOut += sizeof(unsigned long); + + *pData &= bitMaskLeft; + *pData |= curData << iBitsRight; + + pData++; + + if ( iBitsLeft < 32 ) + { + curData >>= iBitsLeft; + *pData &= bitMaskRight; + *pData |= curData; + } + + nBitsLeft -= 32; + m_iCurBit += 32; + } + } + + + // write remaining bytes + while ( nBitsLeft >= 8 ) + { + WriteUBitLong( *pOut, 8, false ); + ++pOut; + nBitsLeft -= 8; + } + + // write remaining bits + if ( nBitsLeft ) + { + WriteUBitLong( *pOut, nBitsLeft, false ); + } + + return !IsOverflowed(); +} + + +bool old_bf_write::WriteBitsFromBuffer( bf_read *pIn, int nBits ) +{ + // This could be optimized a little by + while ( nBits > 32 ) + { + WriteUBitLong( pIn->ReadUBitLong( 32 ), 32 ); + nBits -= 32; + } + + WriteUBitLong( pIn->ReadUBitLong( nBits ), nBits ); + return !IsOverflowed() && !pIn->IsOverflowed(); +} + + +void old_bf_write::WriteBitAngle( float fAngle, int numbits ) +{ + int d; + unsigned int mask; + unsigned int shift; + + shift = BitForBitnum(numbits); + mask = shift - 1; + + d = (int)( (fAngle / 360.0) * shift ); + d &= mask; + + WriteUBitLong((unsigned int)d, numbits); +} + +void old_bf_write::WriteBitCoordMP( const float f, bool bIntegral, bool bLowPrecision ) +{ +#if defined( BB_PROFILING ) + VPROF( "old_bf_write::WriteBitCoordMP" ); +#endif + int signbit = (f <= -( bLowPrecision ? COORD_RESOLUTION_LOWPRECISION : COORD_RESOLUTION )); + int intval = (int)fabs(f); + int fractval = bLowPrecision ? + ( abs((int)(f*COORD_DENOMINATOR_LOWPRECISION)) & (COORD_DENOMINATOR_LOWPRECISION-1) ) : + ( abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1) ); + + + bool bInBounds = intval < (1 << COORD_INTEGER_BITS_MP ); + + WriteOneBit( bInBounds ); + + if ( bIntegral ) + { + // Send the sign bit + WriteOneBit( intval ); + if ( intval ) + { + WriteOneBit( signbit ); + // Send the integer if we have one. + // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] + intval--; + if ( bInBounds ) + { + WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS_MP ); + } + else + { + WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS ); + } + } + } + else + { + // Send the bit flags that indicate whether we have an integer part and/or a fraction part. + WriteOneBit( intval ); + // Send the sign bit + WriteOneBit( signbit ); + + if ( intval ) + { + // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] + intval--; + if ( bInBounds ) + { + WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS_MP ); + } + else + { + WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS ); + } + } + WriteUBitLong( (unsigned int)fractval, bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS ); + } +} + +void old_bf_write::WriteBitCoord (const float f) +{ +#if defined( BB_PROFILING ) + VPROF( "old_bf_write::WriteBitCoord" ); +#endif + int signbit = (f <= -COORD_RESOLUTION); + int intval = (int)fabs(f); + int fractval = abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1); + + + // Send the bit flags that indicate whether we have an integer part and/or a fraction part. + WriteOneBit( intval ); + WriteOneBit( fractval ); + + if ( intval || fractval ) + { + // Send the sign bit + WriteOneBit( signbit ); + + // Send the integer if we have one. + if ( intval ) + { + // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] + intval--; + WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS ); + } + + // Send the fraction if we have one + if ( fractval ) + { + WriteUBitLong( (unsigned int)fractval, COORD_FRACTIONAL_BITS ); + } + } +} + +void old_bf_write::WriteBitFloat(float val) +{ + long intVal; + + Assert(sizeof(long) == sizeof(float)); + Assert(sizeof(float) == 4); + + intVal = *((long*)&val); + WriteUBitLong( intVal, 32 ); +} + +void old_bf_write::WriteBitVec3Coord( const Vector& fa ) +{ + int xflag, yflag, zflag; + + xflag = (fa[0] >= COORD_RESOLUTION) || (fa[0] <= -COORD_RESOLUTION); + yflag = (fa[1] >= COORD_RESOLUTION) || (fa[1] <= -COORD_RESOLUTION); + zflag = (fa[2] >= COORD_RESOLUTION) || (fa[2] <= -COORD_RESOLUTION); + + WriteOneBit( xflag ); + WriteOneBit( yflag ); + WriteOneBit( zflag ); + + if ( xflag ) + WriteBitCoord( fa[0] ); + if ( yflag ) + WriteBitCoord( fa[1] ); + if ( zflag ) + WriteBitCoord( fa[2] ); +} + +void old_bf_write::WriteBitNormal( float f ) +{ + int signbit = (f <= -NORMAL_RESOLUTION); + + // NOTE: Since +/-1 are valid values for a normal, I'm going to encode that as all ones + unsigned int fractval = abs( (int)(f*NORMAL_DENOMINATOR) ); + + // clamp.. + if (fractval > NORMAL_DENOMINATOR) + fractval = NORMAL_DENOMINATOR; + + // Send the sign bit + WriteOneBit( signbit ); + + // Send the fractional component + WriteUBitLong( fractval, NORMAL_FRACTIONAL_BITS ); +} + +void old_bf_write::WriteBitVec3Normal( const Vector& fa ) +{ + int xflag, yflag; + + xflag = (fa[0] >= NORMAL_RESOLUTION) || (fa[0] <= -NORMAL_RESOLUTION); + yflag = (fa[1] >= NORMAL_RESOLUTION) || (fa[1] <= -NORMAL_RESOLUTION); + + WriteOneBit( xflag ); + WriteOneBit( yflag ); + + if ( xflag ) + WriteBitNormal( fa[0] ); + if ( yflag ) + WriteBitNormal( fa[1] ); + + // Write z sign bit + int signbit = (fa[2] <= -NORMAL_RESOLUTION); + WriteOneBit( signbit ); +} + +void old_bf_write::WriteBitAngles( const QAngle& fa ) +{ + // FIXME: + Vector tmp( fa.x, fa.y, fa.z ); + WriteBitVec3Coord( tmp ); +} + +void old_bf_write::WriteChar(int val) +{ + WriteSBitLong(val, sizeof(char) << 3); +} + +void old_bf_write::WriteByte(int val) +{ + WriteUBitLong(val, sizeof(unsigned char) << 3); +} + +void old_bf_write::WriteShort(int val) +{ + WriteSBitLong(val, sizeof(short) << 3); +} + +void old_bf_write::WriteWord(int val) +{ + WriteUBitLong(val, sizeof(unsigned short) << 3); +} + +void old_bf_write::WriteLong(long val) +{ + WriteSBitLong(val, sizeof(long) << 3); +} + +void old_bf_write::WriteLongLong(int64 val) +{ + uint *pLongs = (uint*)&val; + + // Insert the two DWORDS according to network endian + const short endianIndex = 0x0100; + byte *idx = (byte*)&endianIndex; + WriteUBitLong(pLongs[*idx++], sizeof(long) << 3); + WriteUBitLong(pLongs[*idx], sizeof(long) << 3); +} + +void old_bf_write::WriteFloat(float val) +{ + // Pre-swap the float, since WriteBits writes raw data + LittleFloat( &val, &val ); + + WriteBits(&val, sizeof(val) << 3); +} + +bool old_bf_write::WriteBytes( const void *pBuf, int nBytes ) +{ + return WriteBits(pBuf, nBytes << 3); +} + +bool old_bf_write::WriteString(const char *pStr) +{ + if(pStr) + { + do + { + WriteChar( *pStr ); + ++pStr; + } while( *(pStr-1) != 0 ); + } + else + { + WriteChar( 0 ); + } + + return !IsOverflowed(); +} + +// ---------------------------------------------------------------------------------------- // +// old_bf_read +// ---------------------------------------------------------------------------------------- // + +old_bf_read::old_bf_read() +{ + m_pData = NULL; + m_nDataBytes = 0; + m_nDataBits = -1; // set to -1 so we overflow on any operation + m_iCurBit = 0; + m_bOverflow = false; + m_bAssertOnOverflow = true; + m_pDebugName = NULL; +} + +old_bf_read::old_bf_read( const void *pData, int nBytes, int nBits ) +{ + m_bAssertOnOverflow = true; + StartReading( pData, nBytes, 0, nBits ); +} + +old_bf_read::old_bf_read( const char *pDebugName, const void *pData, int nBytes, int nBits ) +{ + m_bAssertOnOverflow = true; + m_pDebugName = pDebugName; + StartReading( pData, nBytes, 0, nBits ); +} + +void old_bf_read::StartReading( const void *pData, int nBytes, int iStartBit, int nBits ) +{ + // Make sure we're dword aligned. + Assert(((unsigned long)pData & 3) == 0); + + m_pData = (unsigned char*)pData; + m_nDataBytes = nBytes; + + if ( nBits == -1 ) + { + m_nDataBits = m_nDataBytes << 3; + } + else + { + Assert( nBits <= nBytes*8 ); + m_nDataBits = nBits; + } + + m_iCurBit = iStartBit; + m_bOverflow = false; +} + +void old_bf_read::Reset() +{ + m_iCurBit = 0; + m_bOverflow = false; +} + +void old_bf_read::SetAssertOnOverflow( bool bAssert ) +{ + m_bAssertOnOverflow = bAssert; +} + +const char* old_bf_read::GetDebugName() +{ + return m_pDebugName; +} + +void old_bf_read::SetDebugName( const char *pName ) +{ + m_pDebugName = pName; +} + +unsigned int old_bf_read::CheckReadUBitLong(int numbits) +{ + // Ok, just read bits out. + int i, nBitValue; + unsigned int r = 0; + + for(i=0; i < numbits; i++) + { + nBitValue = ReadOneBitNoCheck(); + r |= nBitValue << i; + } + m_iCurBit -= numbits; + + return r; +} + +void old_bf_read::ReadBits(void *pOutData, int nBits) +{ +#if defined( BB_PROFILING ) + VPROF( "old_bf_write::ReadBits" ); +#endif + + unsigned char *pOut = (unsigned char*)pOutData; + int nBitsLeft = nBits; + + + // align output to dword boundary + while( ((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8 ) + { + *pOut = (unsigned char)ReadUBitLong(8); + ++pOut; + nBitsLeft -= 8; + } + + // X360TBD: Can't read dwords in ReadBits because they'll get swapped + if ( IsPC() ) + { + // read dwords + while ( nBitsLeft >= 32 ) + { + *((unsigned long*)pOut) = ReadUBitLong(32); + pOut += sizeof(unsigned long); + nBitsLeft -= 32; + } + } + + // read remaining bytes + while ( nBitsLeft >= 8 ) + { + *pOut = ReadUBitLong(8); + ++pOut; + nBitsLeft -= 8; + } + + // read remaining bits + if ( nBitsLeft ) + { + *pOut = ReadUBitLong(nBitsLeft); + } + +} + +float old_bf_read::ReadBitAngle( int numbits ) +{ + float fReturn; + int i; + float shift; + + shift = (float)( BitForBitnum(numbits) ); + + i = ReadUBitLong( numbits ); + fReturn = (float)i * (360.0 / shift); + + return fReturn; +} + +unsigned int old_bf_read::PeekUBitLong( int numbits ) +{ + unsigned int r; + int i, nBitValue; +#ifdef BIT_VERBOSE + int nShifts = numbits; +#endif + + old_bf_read savebf; + + savebf = *this; // Save current state info + + r = 0; + for(i=0; i < numbits; i++) + { + nBitValue = ReadOneBit(); + + // Append to current stream + if ( nBitValue ) + { + r |= BitForBitnum(i); + } + } + + *this = savebf; + +#ifdef BIT_VERBOSE + Con_Printf( "PeekBitLong: %i %i\n", nShifts, (unsigned int)r ); +#endif + + return r; +} + +// Append numbits least significant bits from data to the current bit stream +int old_bf_read::ReadSBitLong( int numbits ) +{ + int r, sign; + + r = ReadUBitLong(numbits - 1); + + // Note: it does this wierdness here so it's bit-compatible with regular integer data in the buffer. + // (Some old code writes direct integers right into the buffer). + sign = ReadOneBit(); + if(sign) + r = -((BitForBitnum(numbits-1)) - r); + + return r; +} + +const byte g_BitMask[8] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; +const byte g_TrailingMask[8] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; + +inline int old_bf_read::CountRunOfZeros() +{ + int bits = 0; + if ( m_iCurBit + 32 < m_nDataBits ) + { +#if !FAST_BIT_SCAN + while (true) + { + int value = (m_pData[m_iCurBit >> 3] & g_BitMask[m_iCurBit & 7]); + ++m_iCurBit; + if ( value ) + return bits; + ++bits; + } +#else + while (true) + { + int value = (m_pData[m_iCurBit >> 3] & g_TrailingMask[m_iCurBit & 7]); + if ( !value ) + { + int zeros = (8-(m_iCurBit&7)); + bits += zeros; + m_iCurBit += zeros; + } + else + { + int zeros = CountTrailingZeros(value) - (m_iCurBit & 7); + m_iCurBit += zeros + 1; + bits += zeros; + return bits; + } + } +#endif + } + else + { + while ( ReadOneBit() == 0 ) + bits++; + } + return bits; +} + +unsigned int old_bf_read::ReadUBitVar() +{ + switch( ReadUBitLong( 2 ) ) + { + case 0: + return ReadUBitLong( 4 ); + + case 1: + return ReadUBitLong( 8 ); + + case 2: + return ReadUBitLong( 12 ); + + default: + case 3: + return ReadUBitLong( 32 ); + } +#if 0 + int bits = CountRunOfZeros(); + + unsigned int data = BitForBitnum(bits)-1; + + // read the value + if ( bits > 0) + data += ReadUBitLong( bits ); + + return data; +#endif +} + + +unsigned int old_bf_read::ReadBitLong(int numbits, bool bSigned) +{ + if(bSigned) + return (unsigned int)ReadSBitLong(numbits); + else + return ReadUBitLong(numbits); +} + + +// Basic Coordinate Routines (these contain bit-field size AND fixed point scaling constants) +float old_bf_read::ReadBitCoord (void) +{ +#if defined( BB_PROFILING ) + VPROF( "old_bf_write::ReadBitCoord" ); +#endif + int intval=0,fractval=0,signbit=0; + float value = 0.0; + + + // Read the required integer and fraction flags + intval = ReadOneBit(); + fractval = ReadOneBit(); + + // If we got either parse them, otherwise it's a zero. + if ( intval || fractval ) + { + // Read the sign bit + signbit = ReadOneBit(); + + // If there's an integer, read it in + if ( intval ) + { + // Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE] + intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1; + } + + // If there's a fraction, read it in + if ( fractval ) + { + fractval = ReadUBitLong( COORD_FRACTIONAL_BITS ); + } + + // Calculate the correct floating point value + value = intval + ((float)fractval * COORD_RESOLUTION); + + // Fixup the sign if negative. + if ( signbit ) + value = -value; + } + + return value; +} + +float old_bf_read::ReadBitCoordMP( bool bIntegral, bool bLowPrecision ) +{ +#if defined( BB_PROFILING ) + VPROF( "old_bf_write::ReadBitCoordMP" ); +#endif + int intval=0,fractval=0,signbit=0; + float value = 0.0; + + + bool bInBounds = ReadOneBit() ? true : false; + + if ( bIntegral ) + { + // Read the required integer and fraction flags + intval = ReadOneBit(); + // If we got either parse them, otherwise it's a zero. + if ( intval ) + { + // Read the sign bit + signbit = ReadOneBit(); + + // If there's an integer, read it in + // Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE] + if ( bInBounds ) + { + value = ReadUBitLong( COORD_INTEGER_BITS_MP ) + 1; + } + else + { + value = ReadUBitLong( COORD_INTEGER_BITS ) + 1; + } + } + } + else + { + // Read the required integer and fraction flags + intval = ReadOneBit(); + + // Read the sign bit + signbit = ReadOneBit(); + + // If we got either parse them, otherwise it's a zero. + if ( intval ) + { + if ( bInBounds ) + { + intval = ReadUBitLong( COORD_INTEGER_BITS_MP ) + 1; + } + else + { + intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1; + } + } + + // If there's a fraction, read it in + fractval = ReadUBitLong( bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS ); + + // Calculate the correct floating point value + value = intval + ((float)fractval * ( bLowPrecision ? COORD_RESOLUTION_LOWPRECISION : COORD_RESOLUTION ) ); + } + + // Fixup the sign if negative. + if ( signbit ) + value = -value; + + return value; +} + +void old_bf_read::ReadBitVec3Coord( Vector& fa ) +{ + int xflag, yflag, zflag; + + // This vector must be initialized! Otherwise, If any of the flags aren't set, + // the corresponding component will not be read and will be stack garbage. + fa.Init( 0, 0, 0 ); + + xflag = ReadOneBit(); + yflag = ReadOneBit(); + zflag = ReadOneBit(); + + if ( xflag ) + fa[0] = ReadBitCoord(); + if ( yflag ) + fa[1] = ReadBitCoord(); + if ( zflag ) + fa[2] = ReadBitCoord(); +} + +float old_bf_read::ReadBitNormal (void) +{ + // Read the sign bit + int signbit = ReadOneBit(); + + // Read the fractional part + unsigned int fractval = ReadUBitLong( NORMAL_FRACTIONAL_BITS ); + + // Calculate the correct floating point value + float value = (float)fractval * NORMAL_RESOLUTION; + + // Fixup the sign if negative. + if ( signbit ) + value = -value; + + return value; +} + +void old_bf_read::ReadBitVec3Normal( Vector& fa ) +{ + int xflag = ReadOneBit(); + int yflag = ReadOneBit(); + + if (xflag) + fa[0] = ReadBitNormal(); + else + fa[0] = 0.0f; + + if (yflag) + fa[1] = ReadBitNormal(); + else + fa[1] = 0.0f; + + // The first two imply the third (but not its sign) + int znegative = ReadOneBit(); + + float fafafbfb = fa[0] * fa[0] + fa[1] * fa[1]; + if (fafafbfb < 1.0f) + fa[2] = sqrt( 1.0f - fafafbfb ); + else + fa[2] = 0.0f; + + if (znegative) + fa[2] = -fa[2]; +} + +void old_bf_read::ReadBitAngles( QAngle& fa ) +{ + Vector tmp; + ReadBitVec3Coord( tmp ); + fa.Init( tmp.x, tmp.y, tmp.z ); +} + +int old_bf_read::ReadChar() +{ + return ReadSBitLong(sizeof(char) << 3); +} + +int old_bf_read::ReadByte() +{ + return ReadUBitLong(sizeof(unsigned char) << 3); +} + +int old_bf_read::ReadShort() +{ + return ReadSBitLong(sizeof(short) << 3); +} + +int old_bf_read::ReadWord() +{ + return ReadUBitLong(sizeof(unsigned short) << 3); +} + +long old_bf_read::ReadLong() +{ + return ReadSBitLong(sizeof(long) << 3); +} + +int64 old_bf_read::ReadLongLong() +{ + int64 retval; + uint *pLongs = (uint*)&retval; + + // Read the two DWORDs according to network endian + const short endianIndex = 0x0100; + byte *idx = (byte*)&endianIndex; + pLongs[*idx++] = ReadUBitLong(sizeof(long) << 3); + pLongs[*idx] = ReadUBitLong(sizeof(long) << 3); + + return retval; +} + +float old_bf_read::ReadFloat() +{ + float ret; + Assert( sizeof(ret) == 4 ); + ReadBits(&ret, 32); + + // Swap the float, since ReadBits reads raw data + LittleFloat( &ret, &ret ); + return ret; +} + +bool old_bf_read::ReadBytes(void *pOut, int nBytes) +{ + ReadBits(pOut, nBytes << 3); + return !IsOverflowed(); +} + +bool old_bf_read::ReadString( char *pStr, int maxLen, bool bLine, int *pOutNumChars ) +{ + Assert( maxLen != 0 ); + + bool bTooSmall = false; + int iChar = 0; + while(1) + { + char val = ReadChar(); + if ( val == 0 ) + break; + else if ( bLine && val == '\n' ) + break; + + if ( iChar < (maxLen-1) ) + { + pStr[iChar] = val; + ++iChar; + } + else + { + bTooSmall = true; + } + } + + // Make sure it's null-terminated. + Assert( iChar < maxLen ); + pStr[iChar] = 0; + + if ( pOutNumChars ) + *pOutNumChars = iChar; + + return !IsOverflowed() && !bTooSmall; +} + + +char* old_bf_read::ReadAndAllocateString( bool *pOverflow ) +{ + char str[2048]; + + int nChars; + bool bOverflow = !ReadString( str, sizeof( str ), false, &nChars ); + if ( pOverflow ) + *pOverflow = bOverflow; + + // Now copy into the output and return it; + char *pRet = new char[ nChars + 1 ]; + for ( int i=0; i <= nChars; i++ ) + pRet[i] = str[i]; + + return pRet; +} + +void old_bf_read::ExciseBits( int startbit, int bitstoremove ) +{ + int endbit = startbit + bitstoremove; + int remaining_to_end = m_nDataBits - endbit; + + old_bf_write temp; + temp.StartWriting( (void *)m_pData, m_nDataBits << 3, startbit ); + + Seek( endbit ); + + for ( int i = 0; i < remaining_to_end; i++ ) + { + temp.WriteOneBit( ReadOneBit() ); + } + + Seek( startbit ); + + m_nDataBits -= bitstoremove; + m_nDataBytes = m_nDataBits >> 3; +} + + diff --git a/tier1/byteswap.cpp b/tier1/byteswap.cpp new file mode 100644 index 00000000..be8645a5 --- /dev/null +++ b/tier1/byteswap.cpp @@ -0,0 +1,90 @@ +//========= Copyright © 1996-2006, Valve LLC, All rights reserved. ============ +// +// Purpose: Low level byte swapping routines. +// +// $NoKeywords: $ +//============================================================================= + +#include "byteswap.h" + +//----------------------------------------------------------------------------- +// Copy a single field from the input buffer to the output buffer, swapping the bytes if necessary +//----------------------------------------------------------------------------- +void CByteswap::SwapFieldToTargetEndian( void* pOutputBuffer, void *pData, typedescription_t *pField ) +{ + switch ( pField->fieldType ) + { + case FIELD_CHARACTER: + SwapBufferToTargetEndian( (char*)pOutputBuffer, (char*)pData, pField->fieldSize ); + break; + + case FIELD_BOOLEAN: + SwapBufferToTargetEndian( (bool*)pOutputBuffer, (bool*)pData, pField->fieldSize ); + break; + + case FIELD_SHORT: + SwapBufferToTargetEndian( (short*)pOutputBuffer, (short*)pData, pField->fieldSize ); + break; + + case FIELD_FLOAT: + SwapBufferToTargetEndian( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize ); + break; + + case FIELD_INTEGER: + SwapBufferToTargetEndian( (int*)pOutputBuffer, (int*)pData, pField->fieldSize ); + break; + + case FIELD_VECTOR: + SwapBufferToTargetEndian( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize * 3 ); + break; + + case FIELD_VECTOR2D: + SwapBufferToTargetEndian( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize * 2 ); + break; + + case FIELD_QUATERNION: + SwapBufferToTargetEndian( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize * 4 ); + break; + + case FIELD_EMBEDDED: + { + typedescription_t *pEmbed = pField->td->dataDesc; + for ( int i = 0; i < pField->fieldSize; ++i ) + { + SwapFieldsToTargetEndian( (byte*)pOutputBuffer + pEmbed->fieldOffset[ TD_OFFSET_NORMAL ], + (byte*)pData + pEmbed->fieldOffset[ TD_OFFSET_NORMAL ], + pField->td ); + + pOutputBuffer = (byte*)pOutputBuffer + pField->fieldSizeInBytes; + pData = (byte*)pData + pField->fieldSizeInBytes; + } + } + break; + + default: + assert(0); + } +} + +//----------------------------------------------------------------------------- +// Write a block of fields. Works a bit like the saverestore code. +//----------------------------------------------------------------------------- +void CByteswap::SwapFieldsToTargetEndian( void *pOutputBuffer, void *pBaseData, datamap_t *pDataMap ) +{ + // deal with base class first + if ( pDataMap->baseMap ) + { + SwapFieldsToTargetEndian( pOutputBuffer, pBaseData, pDataMap->baseMap ); + } + + typedescription_t *pFields = pDataMap->dataDesc; + int fieldCount = pDataMap->dataNumFields; + for ( int i = 0; i < fieldCount; ++i ) + { + typedescription_t *pField = &pFields[i]; + SwapFieldToTargetEndian( (BYTE*)pOutputBuffer + pField->fieldOffset[ TD_OFFSET_NORMAL ], + (BYTE*)pBaseData + pField->fieldOffset[ TD_OFFSET_NORMAL ], + pField ); + } +} + diff --git a/tier1/characterset.cpp b/tier1/characterset.cpp new file mode 100644 index 00000000..8fde2d96 --- /dev/null +++ b/tier1/characterset.cpp @@ -0,0 +1,41 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//============================================================================= + +#include +#include "characterset.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// Purpose: builds a simple lookup table of a group of important characters +// Input : *pParseGroup - pointer to the buffer for the group +// *pGroupString - null terminated list of characters to flag +//----------------------------------------------------------------------------- +void CharacterSetBuild( characterset_t *pSetBuffer, const char *pszSetString ) +{ + int i = 0; + + // Test our pointers + if ( !pSetBuffer || !pszSetString ) + return; + + memset( pSetBuffer->set, 0, sizeof(pSetBuffer->set) ); + + while ( pszSetString[i] ) + { + pSetBuffer->set[ static_cast(pszSetString[i]) ] = 1; + i++; + } + +} diff --git a/tier1/checksum_crc.cpp b/tier1/checksum_crc.cpp new file mode 100644 index 00000000..395e4c67 --- /dev/null +++ b/tier1/checksum_crc.cpp @@ -0,0 +1,180 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: Generic CRC functions +// +//=============================================================================// + +#include "basetypes.h" +#include "commonmacros.h" +#include "checksum_crc.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define CRC32_INIT_VALUE 0xFFFFFFFFUL +#define CRC32_XOR_VALUE 0xFFFFFFFFUL + +#define NUM_BYTES 256 +static const CRC32_t pulCRCTable[NUM_BYTES] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +void CRC32_Init(CRC32_t *pulCRC) +{ + *pulCRC = CRC32_INIT_VALUE; +} + +void CRC32_Final(CRC32_t *pulCRC) +{ + *pulCRC ^= CRC32_XOR_VALUE; +} + +CRC32_t CRC32_GetTableEntry( unsigned int slot ) +{ + return pulCRCTable[(unsigned char)slot]; +} + +void CRC32_ProcessBuffer(CRC32_t *pulCRC, const void *pBuffer, int nBuffer) +{ + CRC32_t ulCrc = *pulCRC; + unsigned char *pb = (unsigned char *)pBuffer; + unsigned int nFront; + int nMain; + +JustAfew: + + switch (nBuffer) + { + case 7: + ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8); + + case 6: + ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8); + + case 5: + ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8); + + case 4: + ulCrc ^= LittleLong( *(CRC32_t *)pb ); + ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8); + ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8); + ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8); + ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8); + *pulCRC = ulCrc; + return; + + case 3: + ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8); + + case 2: + ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8); + + case 1: + ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8); + + case 0: + *pulCRC = ulCrc; + return; + } + + // We may need to do some alignment work up front, and at the end, so that + // the main loop is aligned and only has to worry about 8 byte at a time. + // + // The low-order two bits of pb and nBuffer in total control the + // upfront work. + // + nFront = ((unsigned int)pb) & 3; + nBuffer -= nFront; + switch (nFront) + { + case 3: + ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8); + case 2: + ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8); + case 1: + ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8); + } + + nMain = nBuffer >> 3; + while (nMain--) + { + ulCrc ^= LittleLong( *(CRC32_t *)pb ); + ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8); + ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8); + ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8); + ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8); + ulCrc ^= LittleLong( *(CRC32_t *)(pb + 4) ); + ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8); + ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8); + ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8); + ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8); + pb += 8; + } + + nBuffer &= 7; + goto JustAfew; +} diff --git a/tier1/checksum_md5.cpp b/tier1/checksum_md5.cpp new file mode 100644 index 00000000..983a371f --- /dev/null +++ b/tier1/checksum_md5.cpp @@ -0,0 +1,271 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// + +#include "basetypes.h" +#include "commonmacros.h" +#include "checksum_md5.h" +#include +#include +#include "tier1/strtools.h" +#include "tier0/dbg.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// The four core functions - F1 is optimized somewhat +// #define F1(x, y, z) (x & y | ~x & z) +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +// This is the central step in the MD5 algorithm. +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +//----------------------------------------------------------------------------- +// Purpose: The core of the MD5 algorithm, this alters an existing MD5 hash to +// reflect the addition of 16 longwords of new data. MD5Update blocks +// the data and converts bytes into longwords for this routine. +// Input : buf[4] - +// in[16] - +// Output : static void +//----------------------------------------------------------------------------- +static void MD5Transform(unsigned int buf[4], unsigned int const in[16]) +{ + register unsigned int a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +//----------------------------------------------------------------------------- +// Purpose: Start MD5 accumulation. Set bit count to 0 and buffer to mysterious initialization constants. + +// Input : *ctx - +//----------------------------------------------------------------------------- +void MD5Init(MD5Context_t *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Update context to reflect the concatenation of another buffer full of bytes. +// Input : *ctx - +// *buf - +// len - +//----------------------------------------------------------------------------- +void MD5Update(MD5Context_t *ctx, unsigned char const *buf, unsigned int len) +{ + unsigned int t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((unsigned int) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) + { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) + { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + //byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (unsigned int *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) + { + memcpy(ctx->in, buf, 64); + //byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (unsigned int *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + memcpy(ctx->in, buf, len); +} + +//----------------------------------------------------------------------------- +// Purpose: Final wrapup - pad to 64-byte boundary with the bit pattern +// 1 0* (64-bit count of bits processed, MSB-first) +// Input : digest[MD5_DIGEST_LENGTH] - +// *ctx - +//----------------------------------------------------------------------------- +void MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5Context_t *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) + { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + //byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (unsigned int *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } + else + { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + //byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((unsigned int *) ctx->in)[14] = ctx->bits[0]; + ((unsigned int *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (unsigned int *) ctx->in); + //byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, MD5_DIGEST_LENGTH); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *hash - +// hashlen - +// Output : char +//----------------------------------------------------------------------------- +char *MD5_Print( unsigned char *hash, int hashlen ) +{ + static char szReturn[64]; + + Assert( hashlen <= 32 ); + + Q_binarytohex( hash, hashlen, szReturn, sizeof( szReturn ) ); + return szReturn; +} + +//----------------------------------------------------------------------------- +// Purpose: generate pseudo random number from a seed number +// Input : seed number +// Output : pseudo random number +//----------------------------------------------------------------------------- +unsigned int MD5_PseudoRandom(unsigned int nSeed) +{ + MD5Context_t ctx; + unsigned char digest[MD5_DIGEST_LENGTH]; // The MD5 Hash + + memset( &ctx, 0, sizeof( ctx ) ); + + MD5Init(&ctx); + MD5Update(&ctx, (unsigned char*)&nSeed, sizeof(nSeed) ); + MD5Final(digest, &ctx); + + return *(unsigned int*)(digest+6); // use 4 middle bytes for random value +} diff --git a/tier1/commandbuffer.cpp b/tier1/commandbuffer.cpp new file mode 100644 index 00000000..7cd5a2af --- /dev/null +++ b/tier1/commandbuffer.cpp @@ -0,0 +1,636 @@ +//===== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//===========================================================================// + +#include "tier1/CommandBuffer.h" +#include "tier1/utlbuffer.h" +#include "tier1/strtools.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define MAX_ALIAS_NAME 32 +#define MAX_COMMAND_LENGTH 1024 + +struct cmdalias_t +{ + cmdalias_t *next; + char name[ MAX_ALIAS_NAME ]; + char *value; +}; + + +//----------------------------------------------------------------------------- +// Constructor, destructor +//----------------------------------------------------------------------------- +CCommandBuffer::CCommandBuffer( ) : m_Commands( 32, 32 ) +{ + m_hNextCommand = m_Commands.InvalidIndex(); + m_nWaitDelayTicks = 1; + m_nCurrentTick = 0; + m_nLastTickToProcess = -1; + m_nArgSBufferSize = 0; + m_bIsProcessingCommands = false; + m_nMaxArgSBufferLength = ARGS_BUFFER_LENGTH; +} + +CCommandBuffer::~CCommandBuffer() +{ +} + + +//----------------------------------------------------------------------------- +// Indicates how long to delay when encoutering a 'wait' command +//----------------------------------------------------------------------------- +void CCommandBuffer::SetWaitDelayTime( int nTickDelay ) +{ + Assert( nTickDelay >= 0 ); + m_nWaitDelayTicks = nTickDelay; +} + + +//----------------------------------------------------------------------------- +// Specifies a max limit of the args buffer. For unittesting. Size == 0 means use default +//----------------------------------------------------------------------------- +void CCommandBuffer::LimitArgumentBufferSize( int nSize ) +{ + if ( nSize > ARGS_BUFFER_LENGTH ) + { + nSize = ARGS_BUFFER_LENGTH; + } + + m_nMaxArgSBufferLength = ( nSize == 0 ) ? ARGS_BUFFER_LENGTH : nSize; +} + + +//----------------------------------------------------------------------------- +// Parses argv0 out of the buffer +//----------------------------------------------------------------------------- +bool CCommandBuffer::ParseArgV0( CUtlBuffer &buf, char *pArgV0, int nMaxLen, const char **pArgS ) +{ + pArgV0[0] = 0; + *pArgS = NULL; + + if ( !buf.IsValid() ) + return false; + + int nSize = buf.ParseToken( CCommand::DefaultBreakSet(), pArgV0, nMaxLen ); + if ( ( nSize <= 0 ) || ( nMaxLen == nSize ) ) + return false; + + int nArgSLen = buf.TellMaxPut() - buf.TellGet(); + *pArgS = (nArgSLen > 0) ? (const char*)buf.PeekGet() : NULL; + return true; +} + + +//----------------------------------------------------------------------------- +// Insert a command into the command queue +//----------------------------------------------------------------------------- +void CCommandBuffer::InsertCommandAtAppropriateTime( int hCommand ) +{ + int i; + Command_t &command = m_Commands[hCommand]; + for ( i = m_Commands.Head(); i != m_Commands.InvalidIndex(); i = m_Commands.Next(i) ) + { + if ( m_Commands[i].m_nTick > command.m_nTick ) + break; + } + m_Commands.LinkBefore( i, hCommand ); +} + + +//----------------------------------------------------------------------------- +// Insert a command into the command queue at the appropriate time +//----------------------------------------------------------------------------- +void CCommandBuffer::InsertImmediateCommand( int hCommand ) +{ + m_Commands.LinkBefore( m_hNextCommand, hCommand ); +} + + +//----------------------------------------------------------------------------- +// Insert a command into the command queue +//----------------------------------------------------------------------------- +bool CCommandBuffer::InsertCommand( const char *pArgS, int nCommandSize, int nTick ) +{ + if ( nCommandSize >= CCommand::MaxCommandLength() ) + { + Warning( "WARNING: Command too long... ignoring!\n%s\n", pArgS ); + return false; + } + + // Add one for null termination + if ( m_nArgSBufferSize + nCommandSize + 1 > m_nMaxArgSBufferLength ) + { + Compact(); + if ( m_nArgSBufferSize + nCommandSize + 1 > m_nMaxArgSBufferLength ) + return false; + } + + memcpy( &m_pArgSBuffer[m_nArgSBufferSize], pArgS, nCommandSize ); + m_pArgSBuffer[m_nArgSBufferSize + nCommandSize] = 0; + ++nCommandSize; + + int hCommand = m_Commands.Alloc(); + Command_t &command = m_Commands[hCommand]; + command.m_nTick = nTick; + command.m_nFirstArgS = m_nArgSBufferSize; + command.m_nBufferSize = nCommandSize; + + m_nArgSBufferSize += nCommandSize; + + if ( !m_bIsProcessingCommands || ( nTick > m_nCurrentTick ) ) + { + InsertCommandAtAppropriateTime( hCommand ); + } + else + { + InsertImmediateCommand( hCommand ); + } + return true; +} + + +//----------------------------------------------------------------------------- +// Returns the length of the next command +//----------------------------------------------------------------------------- +void CCommandBuffer::GetNextCommandLength( const char *pText, int nMaxLen, int *pCommandLength, int *pNextCommandOffset ) +{ + int nCommandLength = 0; + int nNextCommandOffset; + bool bIsQuoted = false; + bool bIsCommented = false; + for ( nNextCommandOffset=0; nNextCommandOffset < nMaxLen; ++nNextCommandOffset, nCommandLength += bIsCommented ? 0 : 1 ) + { + char c = pText[nNextCommandOffset]; + if ( !bIsCommented ) + { + if ( c == '"' ) + { + bIsQuoted = !bIsQuoted; + continue; + } + + // don't break if inside a C++ style comment + if ( !bIsQuoted && c == '/' ) + { + bIsCommented = ( nNextCommandOffset < nMaxLen-1 ) && pText[nNextCommandOffset+1] == '/'; + if ( bIsCommented ) + { + ++nNextCommandOffset; + continue; + } + } + + // don't break if inside a quoted string + if ( !bIsQuoted && c == ';' ) + break; + } + + // FIXME: This is legacy behavior; should we not break if a \n is inside a quoted string? + if ( c == '\n' ) + break; + } + + *pCommandLength = nCommandLength; + *pNextCommandOffset = nNextCommandOffset; +} + + +//----------------------------------------------------------------------------- +// Add text to command buffer, return false if it couldn't owing to overflow +//----------------------------------------------------------------------------- +bool CCommandBuffer::AddText( const char *pText, int nTickDelay ) +{ + Assert( nTickDelay >= 0 ); + + int nLen = Q_strlen( pText ); + int nTick = m_nCurrentTick + nTickDelay; + + // Parse the text into distinct commands + const char *pCurrentCommand = pText; + int nOffsetToNextCommand; + for( ; nLen > 0; nLen -= nOffsetToNextCommand+1, pCurrentCommand += nOffsetToNextCommand+1 ) + { + // find a \n or ; line break + int nCommandLength; + GetNextCommandLength( pCurrentCommand, nLen, &nCommandLength, &nOffsetToNextCommand ); + if ( nCommandLength <= 0 ) + continue; + + const char *pArgS; + char *pArgV0 = (char*)_alloca( nCommandLength+1 ); + CUtlBuffer bufParse( pCurrentCommand, nCommandLength, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY ); + ParseArgV0( bufParse, pArgV0, nCommandLength+1, &pArgS ); + if ( pArgV0[0] == 0 ) + continue; + + // Deal with the special 'wait' command + if ( !Q_stricmp( pArgV0, "wait" ) ) + { + int nDelay = pArgS ? atoi( pArgS ) : m_nWaitDelayTicks; + nTick += nDelay; + continue; + } + + if ( !InsertCommand( pCurrentCommand, nCommandLength, nTick ) ) + return false; + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Are we in the middle of processing commands? +//----------------------------------------------------------------------------- +bool CCommandBuffer::IsProcessingCommands() +{ + return m_bIsProcessingCommands; +} + + +//----------------------------------------------------------------------------- +// Delays all queued commands to execute at a later time +//----------------------------------------------------------------------------- +void CCommandBuffer::DelayAllQueuedCommands( int nDelay ) +{ + if ( nDelay <= 0 ) + return; + + for ( int i = m_Commands.Head(); i != m_Commands.InvalidIndex(); i = m_Commands.Next(i) ) + { + m_Commands[i].m_nTick += nDelay; + } +} + + +//----------------------------------------------------------------------------- +// Call this to begin iterating over all commands up to flCurrentTime +//----------------------------------------------------------------------------- +void CCommandBuffer::BeginProcessingCommands( int nDeltaTicks ) +{ + if ( nDeltaTicks == 0 ) + return; + + Assert( !m_bIsProcessingCommands ); + m_bIsProcessingCommands = true; + m_nLastTickToProcess = m_nCurrentTick + nDeltaTicks - 1; + + // Necessary to insert commands while commands are being processed + m_hNextCommand = m_Commands.Head(); +} + + +//----------------------------------------------------------------------------- +// Returns the next command +//----------------------------------------------------------------------------- +bool CCommandBuffer::DequeueNextCommand( ) +{ + m_CurrentCommand.Reset(); + + Assert( m_bIsProcessingCommands ); + if ( m_Commands.Count() == 0 ) + return false; + + int nHead = m_Commands.Head(); + Command_t &command = m_Commands[ nHead ]; + if ( command.m_nTick > m_nLastTickToProcess ) + return false; + + m_nCurrentTick = command.m_nTick; + + // Copy the current command into a temp buffer + // NOTE: This is here to avoid the pointers returned by DequeueNextCommand + // to become invalid by calling AddText. Is there a way we can avoid the memcpy? + if ( command.m_nBufferSize > 0 ) + { + m_CurrentCommand.Tokenize( &m_pArgSBuffer[command.m_nFirstArgS] ); + } + + m_Commands.Remove( nHead ); + + // Necessary to insert commands while commands are being processed + m_hNextCommand = m_Commands.Head(); + +// Msg("Dequeue : "); +// for ( int i = 0; i < nArgc; ++i ) +// { +// Msg("%s ", m_pCurrentArgv[i] ); +// } +// Msg("\n"); + return true; +} + + +//----------------------------------------------------------------------------- +// Returns the next command +//----------------------------------------------------------------------------- +int CCommandBuffer::DequeueNextCommand( const char **& ppArgv ) +{ + DequeueNextCommand(); + ppArgv = ArgV(); + return ArgC(); +} + + +//----------------------------------------------------------------------------- +// Compacts the command buffer +//----------------------------------------------------------------------------- +void CCommandBuffer::Compact() +{ + // Compress argvbuffer + argv + // NOTE: I'm using this choice instead of calling malloc + free + // per command to allocate arguments because I expect to post a + // bunch of commands but not have many delayed commands; + // avoiding the allocation cost seems more important that the memcpy + // cost here since I expect to not have much to copy. + m_nArgSBufferSize = 0; + + char pTempBuffer[ ARGS_BUFFER_LENGTH ]; + for ( int i = m_Commands.Head(); i != m_Commands.InvalidIndex(); i = m_Commands.Next(i) ) + { + Command_t &command = m_Commands[ i ]; + + memcpy( &pTempBuffer[m_nArgSBufferSize], &m_pArgSBuffer[command.m_nFirstArgS], command.m_nBufferSize ); + command.m_nFirstArgS = m_nArgSBufferSize; + m_nArgSBufferSize += command.m_nBufferSize; + } + + // NOTE: We could also store 2 buffers in the command buffer and switch + // between the two to avoid the 2nd memcpy; but again I'm guessing the memory + // tradeoff isn't worth it + memcpy( m_pArgSBuffer, pTempBuffer, m_nArgSBufferSize ); +} + + +//----------------------------------------------------------------------------- +// Call this to finish iterating over all commands +//----------------------------------------------------------------------------- +void CCommandBuffer::EndProcessingCommands() +{ + Assert( m_bIsProcessingCommands ); + m_bIsProcessingCommands = false; + m_nCurrentTick = m_nLastTickToProcess + 1; + m_hNextCommand = m_Commands.InvalidIndex(); + + // Extract commands that are before the end time + // NOTE: This is a bug for this to + int i = m_Commands.Head(); + if ( i == m_Commands.InvalidIndex() ) + { + m_nArgSBufferSize = 0; + return; + } + + while ( i != m_Commands.InvalidIndex() ) + { + if ( m_Commands[i].m_nTick >= m_nCurrentTick ) + break; + + AssertMsgOnce( false, "CCommandBuffer::EndProcessingCommands() called before all appropriate commands were dequeued.\n" ); + int nNext = i; + Msg( "Warning: Skipping command %s\n", m_pArgSBuffer[ m_Commands[i].m_nFirstArgS ] ); + m_Commands.Remove( i ); + i = nNext; + } + + Compact(); +} + + +//----------------------------------------------------------------------------- +// Returns a handle to the next command to process +//----------------------------------------------------------------------------- +CommandHandle_t CCommandBuffer::GetNextCommandHandle() +{ + Assert( m_bIsProcessingCommands ); + return m_Commands.Head(); +} + + +#if 0 +/* +=============== +Cmd_Alias_f + +Creates a new command that executes a command string (possibly ; seperated) +=============== +*/ +void Cmd_Alias_f (void) +{ + cmdalias_t *a; + char cmd[MAX_COMMAND_LENGTH]; + int i, c; + char *s; + + if (Cmd_Argc() == 1) + { + Con_Printf ("Current alias commands:\n"); + for (a = cmd_alias ; a ; a=a->next) + Con_Printf ("%s : %s\n", a->name, a->value); + return; + } + + s = Cmd_Argv(1); + if (strlen(s) >= MAX_ALIAS_NAME) + { + Con_Printf ("Alias name is too long\n"); + return; + } + +// copy the rest of the command line + cmd[0] = 0; // start out with a null string + c = Cmd_Argc(); + for (i=2 ; i< c ; i++) + { + Q_strncat(cmd, Cmd_Argv(i), sizeof( cmd ), COPY_ALL_CHARACTERS); + if (i != c) + { + Q_strncat (cmd, " ", sizeof( cmd ), COPY_ALL_CHARACTERS ); + } + } + Q_strncat (cmd, "\n", sizeof( cmd ), COPY_ALL_CHARACTERS); + + // if the alias already exists, reuse it + for (a = cmd_alias ; a ; a=a->next) + { + if (!strcmp(s, a->name)) + { + if ( !strcmp( a->value, cmd ) ) // Re-alias the same thing + return; + + delete[] a->value; + break; + } + } + + if (!a) + { + a = (cmdalias_t *)new cmdalias_t; + a->next = cmd_alias; + cmd_alias = a; + } + Q_strncpy (a->name, s, sizeof( a->name ) ); + + a->value = COM_StringCopy(cmd); +} + + + +/* +============================================================================= + + COMMAND EXECUTION + +============================================================================= +*/ + +#define MAX_ARGS 80 + +static int cmd_argc; +static char *cmd_argv[MAX_ARGS]; +static char *cmd_null_string = ""; +static const char *cmd_args = NULL; + +cmd_source_t cmd_source; + +//----------------------------------------------------------------------------- +// Purpose: +// Output : void Cmd_Init +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Cmd_Shutdown( void ) +{ + // TODO, cleanup + while ( cmd_alias ) + { + cmdalias_t *next = cmd_alias->next; + delete cmd_alias->value; // created by StringCopy() + delete cmd_alias; + cmd_alias = next; + } +} + + + +/* +============ +Cmd_ExecuteString + +A complete command line has been parsed, so try to execute it +FIXME: lookupnoadd the token to speed search? +============ +*/ +const ConCommandBase *Cmd_ExecuteString (const char *text, cmd_source_t src) +{ + cmdalias_t *a; + + cmd_source = src; + Cmd_TokenizeString (text); + +// execute the command line + if (!Cmd_Argc()) + return NULL; // no tokens + +// check alias + for (a=cmd_alias ; a ; a=a->next) + { + if (!Q_strcasecmp (cmd_argv[0], a->name)) + { + Cbuf_InsertText (a->value); + return NULL; + } + } + +// check ConCommands + ConCommandBase const *pCommand = ConCommandBase::FindCommand( cmd_argv[ 0 ] ); + if ( pCommand && pCommand->IsCommand() ) + { + bool isServerCommand = ( pCommand->IsBitSet( FCVAR_GAMEDLL ) && + // Typed at console + cmd_source == src_command && + // Not HLDS + !sv.IsDedicated() ); + + // Hook to allow game .dll to figure out who type the message on a listen server + if ( serverGameClients ) + { + // We're actually the server, so set it up locally + if ( sv.IsActive() ) + { + g_pServerPluginHandler->SetCommandClient( -1 ); + +#ifndef SWDS + // Special processing for listen server player + if ( isServerCommand ) + { + g_pServerPluginHandler->SetCommandClient( cl.m_nPlayerSlot ); + } +#endif + } + // We're not the server, but we've been a listen server (game .dll loaded) + // forward this command tot he server instead of running it locally if we're still + // connected + // Otherwise, things like "say" won't work unless you quit and restart + else if ( isServerCommand ) + { + if ( cl.IsConnected() ) + { + Cmd_ForwardToServer(); + return NULL; + } + else + { + // It's a server command, but we're not connected to a server. Don't try to execute it. + return NULL; + } + } + } + + // Allow cheat commands in singleplayer, debug, or multiplayer with sv_cheats on +#ifndef _DEBUG + if ( pCommand->IsBitSet( FCVAR_CHEAT ) ) + { + if ( !Host_IsSinglePlayerGame() && sv_cheats.GetInt() == 0 ) + { + Msg( "Can't use cheat command %s in multiplayer, unless the server has sv_cheats set to 1.\n", pCommand->GetName() ); + return NULL; + } + } +#endif + + (( ConCommand * )pCommand )->Dispatch(); + return pCommand; + } + + // check cvars + if ( cv->IsCommand() ) + { + return pCommand; + } + + // forward the command line to the server, so the entity DLL can parse it + if ( cmd_source == src_command ) + { + if ( cl.IsConnected() ) + { + Cmd_ForwardToServer(); + return NULL; + } + } + + Msg("Unknown command \"%s\"\n", Cmd_Argv(0)); + + return NULL; +} +#endif diff --git a/tier1/convar.cpp b/tier1/convar.cpp new file mode 100644 index 00000000..95d101f2 --- /dev/null +++ b/tier1/convar.cpp @@ -0,0 +1,1241 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// + +#include +#include +#include +#include "basetypes.h" +#include "tier1/convar.h" +#include "tier1/strtools.h" +#include "tier1/characterset.h" +#include "tier1/utlbuffer.h" +#include "tier1/tier1.h" +#include "tier1/convar_serverbounded.h" +#include "icvar.h" +#include "tier0/dbg.h" +#include "Color.h" +#if defined( _X360 ) +#include "xbox/xbox_console.h" +#endif +#include "tier0/memdbgon.h" + + +// Comment this out when we release. +//#define ALLOW_DEVELOPMENT_CVARS + + + +//----------------------------------------------------------------------------- +// Statically constructed list of ConCommandBases, +// used for registering them with the ICVar interface +//----------------------------------------------------------------------------- +ConCommandBase *ConCommandBase::s_pConCommandBases = NULL; +IConCommandBaseAccessor *ConCommandBase::s_pAccessor = NULL; +static int s_nCVarFlag = 0; +static int s_nDLLIdentifier = -1; // A unique identifier indicating which DLL this convar came from +static bool s_bRegistered = false; + +class CDefaultAccessor : public IConCommandBaseAccessor +{ +public: + virtual bool RegisterConCommandBase( ConCommandBase *pVar ) + { + // Link to engine's list instead + g_pCVar->RegisterConCommand( pVar ); + return true; + } +}; + +static CDefaultAccessor s_DefaultAccessor; + +//----------------------------------------------------------------------------- +// Called by the framework to register ConCommandBases with the ICVar +//----------------------------------------------------------------------------- +void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor ) +{ + if ( !g_pCVar || s_bRegistered ) + return; + + Assert( s_nDLLIdentifier < 0 ); + s_bRegistered = true; + s_nCVarFlag = nCVarFlag; + s_nDLLIdentifier = g_pCVar->AllocateDLLIdentifier(); + + ConCommandBase *pCur, *pNext; + + ConCommandBase::s_pAccessor = pAccessor ? pAccessor : &s_DefaultAccessor; + pCur = ConCommandBase::s_pConCommandBases; + while ( pCur ) + { + pNext = pCur->m_pNext; + pCur->AddFlags( s_nCVarFlag ); + pCur->Init(); + pCur = pNext; + } + + ConCommandBase::s_pConCommandBases = NULL; +} + +void ConVar_Unregister( ) +{ + if ( !g_pCVar || !s_bRegistered ) + return; + + Assert( s_nDLLIdentifier >= 0 ); + g_pCVar->UnregisterConCommands( s_nDLLIdentifier ); + s_nDLLIdentifier = -1; + s_bRegistered = false; +} + + +//----------------------------------------------------------------------------- +// Purpose: Default constructor +//----------------------------------------------------------------------------- +ConCommandBase::ConCommandBase( void ) +{ + m_bRegistered = false; + m_pszName = NULL; + m_pszHelpString = NULL; + + m_nFlags = 0; + m_pNext = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: The base console invoked command/cvar interface +// Input : *pName - name of variable/command +// *pHelpString - help text +// flags - flags +//----------------------------------------------------------------------------- +ConCommandBase::ConCommandBase( const char *pName, const char *pHelpString /*=0*/, int flags /*= 0*/ ) +{ + Create( pName, pHelpString, flags ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +ConCommandBase::~ConCommandBase( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool ConCommandBase::IsCommand( void ) const +{ +// Assert( 0 ); This can't assert. . causes a recursive assert in Sys_Printf, etc. + return true; +} + + +//----------------------------------------------------------------------------- +// Returns the DLL identifier +//----------------------------------------------------------------------------- +CVarDLLIdentifier_t ConCommandBase::GetDLLIdentifier() const +{ + return s_nDLLIdentifier; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pName - +// callback - +// *pHelpString - +// flags - +//----------------------------------------------------------------------------- +void ConCommandBase::Create( const char *pName, const char *pHelpString /*= 0*/, int flags /*= 0*/ ) +{ + static const char *empty_string = ""; + + m_bRegistered = false; + + // Name should be static data + Assert( pName ); + m_pszName = pName; + m_pszHelpString = pHelpString ? pHelpString : empty_string; + + m_nFlags = flags; + +#ifdef ALLOW_DEVELOPMENT_CVARS + m_nFlags &= ~FCVAR_DEVELOPMENTONLY; +#endif + + if ( !( m_nFlags & FCVAR_UNREGISTERED ) ) + { + m_pNext = s_pConCommandBases; + s_pConCommandBases = this; + } + else + { + // It's unregistered + m_pNext = NULL; + } + + // If s_pAccessor is already set (this ConVar is not a global variable), + // register it. + if ( s_pAccessor ) + { + Init(); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Used internally by OneTimeInit to initialize. +//----------------------------------------------------------------------------- +void ConCommandBase::Init() +{ + if ( s_pAccessor ) + { + s_pAccessor->RegisterConCommandBase( this ); + } +} + +void ConCommandBase::Shutdown() +{ + if ( g_pCVar ) + { + g_pCVar->UnregisterConCommand( this ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Return name of the command/var +// Output : const char +//----------------------------------------------------------------------------- +const char *ConCommandBase::GetName( void ) const +{ + return m_pszName; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : flag - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool ConCommandBase::IsFlagSet( int flag ) const +{ + return ( flag & m_nFlags ) ? true : false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : flags - +//----------------------------------------------------------------------------- +void ConCommandBase::AddFlags( int flags ) +{ + m_nFlags |= flags; + +#ifdef ALLOW_DEVELOPMENT_CVARS + m_nFlags &= ~FCVAR_DEVELOPMENTONLY; +#endif +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const ConCommandBase +//----------------------------------------------------------------------------- +const ConCommandBase *ConCommandBase::GetNext( void ) const +{ + return m_pNext; +} + +ConCommandBase *ConCommandBase::GetNext( void ) +{ + return m_pNext; +} + + +//----------------------------------------------------------------------------- +// Purpose: Copies string using local new/delete operators +// Input : *from - +// Output : char +//----------------------------------------------------------------------------- +char *ConCommandBase::CopyString( const char *from ) +{ + int len; + char *to; + + len = strlen( from ); + if ( len <= 0 ) + { + to = new char[1]; + to[0] = 0; + } + else + { + to = new char[len+1]; + Q_strncpy( to, from, len+1 ); + } + return to; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char *ConCommandBase::GetHelpText( void ) const +{ + return m_pszHelpString; +} + +//----------------------------------------------------------------------------- +// Purpose: Has this cvar been registered +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool ConCommandBase::IsRegistered( void ) const +{ + return m_bRegistered; +} + + +//----------------------------------------------------------------------------- +// +// Con Commands start here +// +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Global methods +//----------------------------------------------------------------------------- +static characterset_t s_BreakSet; +static bool s_bBuiltBreakSet = false; + + +//----------------------------------------------------------------------------- +// Tokenizer class +//----------------------------------------------------------------------------- +CCommand::CCommand() +{ + if ( !s_bBuiltBreakSet ) + { + s_bBuiltBreakSet = true; + CharacterSetBuild( &s_BreakSet, "{}()':" ); + } + + Reset(); +} + +CCommand::CCommand( int nArgC, const char **ppArgV ) +{ + Assert( nArgC > 0 ); + + if ( !s_bBuiltBreakSet ) + { + s_bBuiltBreakSet = true; + CharacterSetBuild( &s_BreakSet, "{}()':" ); + } + + Reset(); + + char *pBuf = m_pArgvBuffer; + char *pSBuf = m_pArgSBuffer; + m_nArgc = nArgC; + for ( int i = 0; i < nArgC; ++i ) + { + m_ppArgv[i] = pBuf; + int nLen = Q_strlen( ppArgV[i] ); + memcpy( pBuf, ppArgV[i], nLen+1 ); + if ( i == 0 ) + { + m_nArgv0Size = nLen; + } + pBuf += nLen+1; + + bool bContainsSpace = strchr( ppArgV[i], ' ' ) != NULL; + if ( bContainsSpace ) + { + *pSBuf++ = '\"'; + } + memcpy( pSBuf, ppArgV[i], nLen ); + pSBuf += nLen; + if ( bContainsSpace ) + { + *pSBuf++ = '\"'; + } + + if ( i != nArgC - 1 ) + { + *pSBuf++ = ' '; + } + } +} + +void CCommand::Reset() +{ + m_nArgc = 0; + m_nArgv0Size = 0; + m_pArgSBuffer[0] = 0; +} + +characterset_t* CCommand::DefaultBreakSet() +{ + return &s_BreakSet; +} + +bool CCommand::Tokenize( const char *pCommand, characterset_t *pBreakSet ) +{ + Reset(); + if ( !pCommand ) + return false; + + // Use default break set + if ( !pBreakSet ) + { + pBreakSet = &s_BreakSet; + } + + // Copy the current command into a temp buffer + // NOTE: This is here to avoid the pointers returned by DequeueNextCommand + // to become invalid by calling AddText. Is there a way we can avoid the memcpy? + int nLen = Q_strlen( pCommand ); + if ( nLen >= COMMAND_MAX_LENGTH - 1 ) + { + Warning( "CCommand::Tokenize: Encountered command which overflows the tokenizer buffer.. Skipping!\n" ); + return false; + } + + memcpy( m_pArgSBuffer, pCommand, nLen + 1 ); + + // Parse the current command into the current command buffer + CUtlBuffer bufParse( m_pArgSBuffer, nLen, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY ); + int nArgvBufferSize = 0; + while ( bufParse.IsValid() && ( m_nArgc < COMMAND_MAX_ARGC ) ) + { + char *pArgvBuf = &m_pArgvBuffer[nArgvBufferSize]; + int nMaxLen = COMMAND_MAX_LENGTH - nArgvBufferSize; + int nStartGet = bufParse.TellGet(); + int nSize = bufParse.ParseToken( pBreakSet, pArgvBuf, nMaxLen ); + if ( nSize < 0 ) + break; + + // Check for overflow condition + if ( nMaxLen == nSize ) + { + Reset(); + return false; + } + + if ( m_nArgc == 1 ) + { + // Deal with the case where the arguments were quoted + m_nArgv0Size = bufParse.TellGet(); + bool bFoundEndQuote = m_pArgSBuffer[m_nArgv0Size-1] == '\"'; + if ( bFoundEndQuote ) + { + --m_nArgv0Size; + } + m_nArgv0Size -= nSize; + Assert( m_nArgv0Size != 0 ); + + // The StartGet check is to handle this case: "foo"bar + // which will parse into 2 different args. ArgS should point to bar. + bool bFoundStartQuote = ( m_nArgv0Size > nStartGet ) && ( m_pArgSBuffer[m_nArgv0Size-1] == '\"' ); + Assert( bFoundEndQuote == bFoundStartQuote ); + if ( bFoundStartQuote ) + { + --m_nArgv0Size; + } + } + + m_ppArgv[ m_nArgc++ ] = pArgvBuf; + if( m_nArgc >= COMMAND_MAX_ARGC ) + { + Warning( "CCommand::Tokenize: Encountered command which overflows the argument buffer.. Clamped!\n" ); + } + + nArgvBufferSize += nSize + 1; + Assert( nArgvBufferSize <= COMMAND_MAX_LENGTH ); + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Helper function to parse arguments to commands. +//----------------------------------------------------------------------------- +const char* CCommand::FindArg( const char *pName ) const +{ + int nArgC = ArgC(); + for ( int i = 1; i < nArgC; i++ ) + { + if ( !Q_stricmp( Arg(i), pName ) ) + return (i+1) < nArgC ? Arg( i+1 ) : ""; + } + return 0; +} + +int CCommand::FindArgInt( const char *pName, int nDefaultVal ) const +{ + const char *pVal = FindArg( pName ); + if ( pVal ) + return atoi( pVal ); + else + return nDefaultVal; +} + + +//----------------------------------------------------------------------------- +// Default console command autocompletion function +//----------------------------------------------------------------------------- +int DefaultCompletionFunc( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ) +{ + return 0; +} + + +//----------------------------------------------------------------------------- +// Purpose: Constructs a console command +//----------------------------------------------------------------------------- +//ConCommand::ConCommand() +//{ +// m_bIsNewConCommand = true; +//} + +ConCommand::ConCommand( const char *pName, FnCommandCallbackV1_t callback, const char *pHelpString /*= 0*/, int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) +{ + // Set the callback + m_fnCommandCallbackV1 = callback; + m_bUsingNewCommandCallback = false; + m_bUsingCommandCallbackInterface = false; + m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + m_bHasCompletionCallback = completionFunc != 0 ? true : false; + + // Setup the rest + BaseClass::Create( pName, pHelpString, flags ); +} + +ConCommand::ConCommand( const char *pName, FnCommandCallback_t callback, const char *pHelpString /*= 0*/, int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) +{ + // Set the callback + m_fnCommandCallback = callback; + m_bUsingNewCommandCallback = true; + m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + m_bHasCompletionCallback = completionFunc != 0 ? true : false; + m_bUsingCommandCallbackInterface = false; + + // Setup the rest + BaseClass::Create( pName, pHelpString, flags ); +} + +ConCommand::ConCommand( const char *pName, ICommandCallback *pCallback, const char *pHelpString /*= 0*/, int flags /*= 0*/, ICommandCompletionCallback *pCompletionCallback /*= 0*/ ) +{ + // Set the callback + m_pCommandCallback = pCallback; + m_bUsingNewCommandCallback = false; + m_pCommandCompletionCallback = pCompletionCallback; + m_bHasCompletionCallback = ( pCompletionCallback != 0 ); + m_bUsingCommandCallbackInterface = true; + + // Setup the rest + BaseClass::Create( pName, pHelpString, flags ); +} + +//----------------------------------------------------------------------------- +// Destructor +//----------------------------------------------------------------------------- +ConCommand::~ConCommand( void ) +{ +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns true if this is a command +//----------------------------------------------------------------------------- +bool ConCommand::IsCommand( void ) const +{ + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Invoke the function if there is one +//----------------------------------------------------------------------------- +void ConCommand::Dispatch( const CCommand &command ) +{ + if ( m_bUsingNewCommandCallback ) + { + if ( m_fnCommandCallback ) + { + ( *m_fnCommandCallback )( command ); + return; + } + } + else if ( m_bUsingCommandCallbackInterface ) + { + if ( m_pCommandCallback ) + { + m_pCommandCallback->CommandCallback( command ); + return; + } + } + else + { + if ( m_fnCommandCallbackV1 ) + { + ( *m_fnCommandCallbackV1 )(); + return; + } + } + + // Command without callback!!! + AssertMsg( 0, ( "Encountered ConCommand without a callback!\n" ) ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Calls the autocompletion method to get autocompletion suggestions +//----------------------------------------------------------------------------- +int ConCommand::AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands ) +{ + if ( m_bUsingCommandCallbackInterface ) + { + if ( !m_pCommandCompletionCallback ) + return 0; + return m_pCommandCompletionCallback->CommandCompletionCallback( partial, commands ); + } + + Assert( m_fnCompletionCallback ); + if ( !m_fnCompletionCallback ) + return 0; + + char rgpchCommands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ]; + int iret = ( m_fnCompletionCallback )( partial, rgpchCommands ); + for ( int i = 0 ; i < iret; ++i ) + { + CUtlString str = rgpchCommands[ i ]; + commands.AddToTail( str ); + } + return iret; +} + + +//----------------------------------------------------------------------------- +// Returns true if the console command can autocomplete +//----------------------------------------------------------------------------- +bool ConCommand::CanAutoComplete( void ) +{ + return m_bHasCompletionCallback; +} + + + +//----------------------------------------------------------------------------- +// +// Console Variables +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Various constructors +//----------------------------------------------------------------------------- +ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags /* = 0 */ ) +{ + Create( pName, pDefaultValue, flags ); +} + +ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags, const char *pHelpString ) +{ + Create( pName, pDefaultValue, flags, pHelpString ); +} + +ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags, const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) +{ + Create( pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax ); +} + +ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags, const char *pHelpString, FnChangeCallback_t callback ) +{ + Create( pName, pDefaultValue, flags, pHelpString, false, 0.0, false, 0.0, callback ); +} + +ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags, const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t callback ) +{ + Create( pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax, callback ); +} + + +//----------------------------------------------------------------------------- +// Destructor +//----------------------------------------------------------------------------- +ConVar::~ConVar( void ) +{ + if ( m_pszString ) + { + delete[] m_pszString; + m_pszString = NULL; + } +} + + +//----------------------------------------------------------------------------- +// Install a change callback (there shouldn't already be one....) +//----------------------------------------------------------------------------- +void ConVar::InstallChangeCallback( FnChangeCallback_t callback ) +{ + Assert( !m_pParent->m_fnChangeCallback || !callback ); + m_pParent->m_fnChangeCallback = callback; + + if ( m_pParent->m_fnChangeCallback ) + { + // Call it immediately to set the initial value... + m_pParent->m_fnChangeCallback( this, m_pszString, m_fValue ); + } +} + +bool ConVar::IsFlagSet( int flag ) const +{ + return ( flag & m_pParent->m_nFlags ) ? true : false; +} + +const char *ConVar::GetHelpText( void ) const +{ + return m_pParent->m_pszHelpString; +} + +void ConVar::AddFlags( int flags ) +{ + m_pParent->m_nFlags |= flags; + +#ifdef ALLOW_DEVELOPMENT_CVARS + m_pParent->m_nFlags &= ~FCVAR_DEVELOPMENTONLY; +#endif +} + +bool ConVar::IsRegistered( void ) const +{ + return m_pParent->m_bRegistered; +} + +const char *ConVar::GetName( void ) const +{ + return m_pParent->m_pszName; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool ConVar::IsCommand( void ) const +{ + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +//----------------------------------------------------------------------------- +void ConVar::Init() +{ + BaseClass::Init(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *value - +//----------------------------------------------------------------------------- +void ConVar::InternalSetValue( const char *value ) +{ + float fNewValue; + char tempVal[ 32 ]; + char *val; + + Assert(m_pParent == this); // Only valid for root convars. + + float flOldValue = m_fValue; + + val = (char *)value; + fNewValue = ( float )atof( value ); + + if ( ClampValue( fNewValue ) ) + { + Q_snprintf( tempVal,sizeof(tempVal), "%f", fNewValue ); + val = tempVal; + } + + // Redetermine value + m_fValue = fNewValue; + m_nValue = ( int )( m_fValue ); + + if ( !( m_nFlags & FCVAR_NEVER_AS_STRING ) ) + { + ChangeStringValue( val, flOldValue ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *tempVal - +//----------------------------------------------------------------------------- +void ConVar::ChangeStringValue( const char *tempVal, float flOldValue ) +{ + Assert( !( m_nFlags & FCVAR_NEVER_AS_STRING ) ); + + char* pszOldValue = (char*)stackalloc( m_StringLength ); + memcpy( pszOldValue, m_pszString, m_StringLength ); + + int len = Q_strlen(tempVal) + 1; + + if ( len > m_StringLength) + { + if (m_pszString) + { + delete[] m_pszString; + } + + m_pszString = new char[len]; + m_StringLength = len; + } + + memcpy( m_pszString, tempVal, len ); + + // Invoke any necessary callback function + if ( m_fnChangeCallback ) + { + m_fnChangeCallback( this, pszOldValue, flOldValue ); + } + + g_pCVar->CallGlobalChangeCallbacks( this, pszOldValue, flOldValue ); + + stackfree( pszOldValue ); +} + +//----------------------------------------------------------------------------- +// Purpose: Check whether to clamp and then perform clamp +// Input : value - +// Output : Returns true if value changed +//----------------------------------------------------------------------------- +bool ConVar::ClampValue( float& value ) +{ + if ( m_bHasMin && ( value < m_fMinVal ) ) + { + value = m_fMinVal; + return true; + } + + if ( m_bHasMax && ( value > m_fMaxVal ) ) + { + value = m_fMaxVal; + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *value - +//----------------------------------------------------------------------------- +void ConVar::InternalSetFloatValue( float fNewValue ) +{ + if ( fNewValue == m_fValue ) + return; + + Assert( m_pParent == this ); // Only valid for root convars. + + // Check bounds + ClampValue( fNewValue ); + + // Redetermine value + float flOldValue = m_fValue; + m_fValue = fNewValue; + m_nValue = ( int )m_fValue; + + if ( !( m_nFlags & FCVAR_NEVER_AS_STRING ) ) + { + char tempVal[ 32 ]; + Q_snprintf( tempVal, sizeof( tempVal), "%f", m_fValue ); + ChangeStringValue( tempVal, flOldValue ); + } + else + { + Assert( !m_fnChangeCallback ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *value - +//----------------------------------------------------------------------------- +void ConVar::InternalSetIntValue( int nValue ) +{ + if ( nValue == m_nValue ) + return; + + Assert( m_pParent == this ); // Only valid for root convars. + + float fValue = (float)nValue; + if ( ClampValue( fValue ) ) + { + nValue = ( int )( fValue ); + } + + // Redetermine value + float flOldValue = m_fValue; + m_fValue = fValue; + m_nValue = nValue; + + if ( !( m_nFlags & FCVAR_NEVER_AS_STRING ) ) + { + char tempVal[ 32 ]; + Q_snprintf( tempVal, sizeof( tempVal ), "%d", m_nValue ); + ChangeStringValue( tempVal, flOldValue ); + } + else + { + Assert( !m_fnChangeCallback ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Private creation +//----------------------------------------------------------------------------- +void ConVar::Create( const char *pName, const char *pDefaultValue, int flags /*= 0*/, + const char *pHelpString /*= NULL*/, bool bMin /*= false*/, float fMin /*= 0.0*/, + bool bMax /*= false*/, float fMax /*= false*/, FnChangeCallback_t callback /*= NULL*/ ) +{ + static const char *empty_string = ""; + + m_pParent = this; + + // Name should be static data + m_pszDefaultValue = pDefaultValue ? pDefaultValue : empty_string; + Assert( m_pszDefaultValue ); + + m_StringLength = strlen( m_pszDefaultValue ) + 1; + m_pszString = new char[m_StringLength]; + memcpy( m_pszString, m_pszDefaultValue, m_StringLength ); + + m_bHasMin = bMin; + m_fMinVal = fMin; + m_bHasMax = bMax; + m_fMaxVal = fMax; + + m_fnChangeCallback = callback; + + m_fValue = ( float )atof( m_pszString ); + + // Bounds Check, should never happen, if it does, no big deal + if ( m_bHasMin && ( m_fValue < m_fMinVal ) ) + { + Assert( 0 ); + } + + if ( m_bHasMax && ( m_fValue > m_fMaxVal ) ) + { + Assert( 0 ); + } + + m_nValue = ( int )m_fValue; + + BaseClass::Create( pName, pHelpString, flags ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *value - +//----------------------------------------------------------------------------- +void ConVar::SetValue(const char *value) +{ + ConVar *var = ( ConVar * )m_pParent; + var->InternalSetValue( value ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : value - +//----------------------------------------------------------------------------- +void ConVar::SetValue( float value ) +{ + ConVar *var = ( ConVar * )m_pParent; + var->InternalSetFloatValue( value ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : value - +//----------------------------------------------------------------------------- +void ConVar::SetValue( int value ) +{ + ConVar *var = ( ConVar * )m_pParent; + var->InternalSetIntValue( value ); +} + +//----------------------------------------------------------------------------- +// Purpose: Reset to default value +//----------------------------------------------------------------------------- +void ConVar::Revert( void ) +{ + // Force default value again + ConVar *var = ( ConVar * )m_pParent; + var->SetValue( var->m_pszDefaultValue ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : minVal - +// Output : true if there is a min set +//----------------------------------------------------------------------------- +bool ConVar::GetMin( float& minVal ) const +{ + minVal = m_pParent->m_fMinVal; + return m_pParent->m_bHasMin; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : maxVal - +//----------------------------------------------------------------------------- +bool ConVar::GetMax( float& maxVal ) const +{ + maxVal = m_pParent->m_fMaxVal; + return m_pParent->m_bHasMax; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char *ConVar::GetDefault( void ) const +{ + return m_pParent->m_pszDefaultValue; +} + + +//----------------------------------------------------------------------------- +// This version is simply used to make reading convars simpler. +// Writing convars isn't allowed in this mode +//----------------------------------------------------------------------------- +class CEmptyConVar : public ConVar +{ +public: + CEmptyConVar() : ConVar( "", "0" ) {} + // Used for optimal read access + virtual void SetValue( const char *pValue ) {} + virtual void SetValue( float flValue ) {} + virtual void SetValue( int nValue ) {} + virtual const char *GetName( void ) const { return ""; } + virtual bool IsFlagSet( int nFlags ) const { return false; } +}; + +static CEmptyConVar s_EmptyConVar; + +ConVarRef::ConVarRef( const char *pName ) +{ + Init( pName, false ); +} + +ConVarRef::ConVarRef( const char *pName, bool bIgnoreMissing ) +{ + Init( pName, bIgnoreMissing ); +} + +void ConVarRef::Init( const char *pName, bool bIgnoreMissing ) +{ + m_pConVar = g_pCVar ? g_pCVar->FindVar( pName ) : &s_EmptyConVar; + if ( !m_pConVar ) + { + m_pConVar = &s_EmptyConVar; + } + m_pConVarState = static_cast< ConVar * >( m_pConVar ); + if( !IsValid() ) + { + static bool bFirst = true; + if ( g_pCVar || bFirst ) + { + if ( !bIgnoreMissing ) + { + Warning( "ConVarRef %s doesn't point to an existing ConVar\n", pName ); + } + bFirst = false; + } + } +} + +ConVarRef::ConVarRef( IConVar *pConVar ) +{ + m_pConVar = pConVar ? pConVar : &s_EmptyConVar; + m_pConVarState = static_cast< ConVar * >( m_pConVar ); +} + +bool ConVarRef::IsValid() const +{ + return m_pConVar != &s_EmptyConVar; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ConVar_PrintFlags( const ConCommandBase *var ) +{ + bool any = false; + if ( var->IsFlagSet( FCVAR_GAMEDLL ) ) + { + ConMsg( " game" ); + any = true; + } + + if ( var->IsFlagSet( FCVAR_CLIENTDLL ) ) + { + ConMsg( " client" ); + any = true; + } + + if ( var->IsFlagSet( FCVAR_ARCHIVE ) ) + { + ConMsg( " archive" ); + any = true; + } + + if ( var->IsFlagSet( FCVAR_NOTIFY ) ) + { + ConMsg( " notify" ); + any = true; + } + + if ( var->IsFlagSet( FCVAR_SPONLY ) ) + { + ConMsg( " singleplayer" ); + any = true; + } + + if ( var->IsFlagSet( FCVAR_NOT_CONNECTED ) ) + { + ConMsg( " notconnected" ); + any = true; + } + + if ( var->IsFlagSet( FCVAR_CHEAT ) ) + { + ConMsg( " cheat" ); + any = true; + } + + if ( var->IsFlagSet( FCVAR_REPLICATED ) ) + { + ConMsg( " replicated" ); + any = true; + } + + if ( var->IsFlagSet( FCVAR_SERVER_CAN_EXECUTE ) ) + { + ConMsg( " server_can_execute" ); + any = true; + } + + if ( var->IsFlagSet( FCVAR_CLIENTCMD_CAN_EXECUTE ) ) + { + ConMsg( " clientcmd_can_execute" ); + any = true; + } + + if ( any ) + { + ConMsg( "\n" ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ConVar_PrintDescription( const ConCommandBase *pVar ) +{ + bool bMin, bMax; + float fMin, fMax; + const char *pStr; + + assert( pVar ); + + Color clr; + clr.SetColor( 255, 100, 100, 255 ); + + if ( !pVar->IsCommand() ) + { + ConVar *var = ( ConVar * )pVar; + const ConVar_ServerBounded *pBounded = dynamic_cast( var ); + + bMin = var->GetMin( fMin ); + bMax = var->GetMax( fMax ); + + const char *value = NULL; + char tempVal[ 32 ]; + + if ( pBounded || var->IsFlagSet( FCVAR_NEVER_AS_STRING ) ) + { + value = tempVal; + + int intVal = pBounded ? pBounded->GetInt() : var->GetInt(); + float floatVal = pBounded ? pBounded->GetFloat() : var->GetFloat(); + + if ( fabs( (float)intVal - floatVal ) < 0.000001 ) + { + Q_snprintf( tempVal, sizeof( tempVal ), "%d", intVal ); + } + else + { + Q_snprintf( tempVal, sizeof( tempVal ), "%f", floatVal ); + } + } + else + { + value = var->GetString(); + } + + if ( value ) + { + ConColorMsg( clr, "\"%s\" = \"%s\"", var->GetName(), value ); + + if ( stricmp( value, var->GetDefault() ) ) + { + ConMsg( " ( def. \"%s\" )", var->GetDefault() ); + } + } + + if ( bMin ) + { + ConMsg( " min. %f", fMin ); + } + if ( bMax ) + { + ConMsg( " max. %f", fMax ); + } + + ConMsg( "\n" ); + + // Handled virtualized cvars. + if ( pBounded && fabs( pBounded->GetFloat() - var->GetFloat() ) > 0.0001f ) + { + ConColorMsg( clr, "** NOTE: The real value is %.3f but the server has temporarily restricted it to %.3f **\n", + var->GetFloat(), pBounded->GetFloat() ); + } + } + else + { + ConCommand *var = ( ConCommand * )pVar; + + ConColorMsg( clr, "\"%s\"\n", var->GetName() ); + } + + ConVar_PrintFlags( pVar ); + + pStr = pVar->GetHelpText(); + if ( pStr && pStr[0] ) + { + ConMsg( " - %s\n", pStr ); + } +} diff --git a/tier1/datamanager.cpp b/tier1/datamanager.cpp new file mode 100644 index 00000000..596024d0 --- /dev/null +++ b/tier1/datamanager.cpp @@ -0,0 +1,410 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include "basetypes.h" +#include "datamanager.h" + +DECLARE_POINTER_HANDLE( memhandle_t ); + +#define AUTO_LOCK_DM() AUTO_LOCK_( CDataManagerBase, *this ) + +CDataManagerBase::CDataManagerBase( unsigned int maxSize ) +{ + m_targetMemorySize = maxSize; + m_memUsed = 0; + m_lruList = m_memoryLists.CreateList(); + m_lockList = m_memoryLists.CreateList(); + m_freeList = m_memoryLists.CreateList(); + m_listsAreFreed = 0; +} + +CDataManagerBase::~CDataManagerBase() +{ + Assert( m_listsAreFreed ); +} + +void CDataManagerBase::NotifySizeChanged( memhandle_t handle, unsigned int oldSize, unsigned int newSize ) +{ + Lock(); + m_memUsed += (int)newSize - (int)oldSize; + Unlock(); +} + +void CDataManagerBase::SetTargetSize( unsigned int targetSize ) +{ + m_targetMemorySize = targetSize; +} + +unsigned int CDataManagerBase::FlushAllUnlocked() +{ + Lock(); + + int nFlush = m_memoryLists.Count( m_lruList ); + void **pScratch = (void **)_alloca( nFlush * sizeof(void *) ); + CUtlVector destroyList( pScratch, nFlush ); + + unsigned nBytesInitial = MemUsed_Inline(); + + int node = m_memoryLists.Head(m_lruList); + while ( node != m_memoryLists.InvalidIndex() ) + { + int next = m_memoryLists.Next(node); + m_memoryLists.Unlink( m_lruList, node ); + destroyList.AddToTail( GetForFreeByIndex( node ) ); + node = next; + } + + Unlock(); + + for ( int i = 0; i < nFlush; i++ ) + { + DestroyResourceStorage( destroyList[i] ); + } + + return ( nBytesInitial - MemUsed_Inline() ); +} + +unsigned int CDataManagerBase::FlushToTargetSize() +{ + return EnsureCapacity(0); +} + +// Frees everything! The LRU AND the LOCKED items. This is only used to forcibly free the resources, +// not to make space. + +unsigned int CDataManagerBase::FlushAll() +{ + Lock(); + + int nFlush = m_memoryLists.Count( m_lruList ) + m_memoryLists.Count( m_lockList ); + void **pScratch = (void **)_alloca( nFlush * sizeof(void *) ); + CUtlVector destroyList( pScratch, nFlush ); + + unsigned result = MemUsed_Inline(); + int node; + int nextNode; + + node = m_memoryLists.Head(m_lruList); + while ( node != m_memoryLists.InvalidIndex() ) + { + nextNode = m_memoryLists.Next(node); + m_memoryLists.Unlink( m_lruList, node ); + destroyList.AddToTail( GetForFreeByIndex( node ) ); + node = nextNode; + } + + node = m_memoryLists.Head(m_lockList); + while ( node != m_memoryLists.InvalidIndex() ) + { + nextNode = m_memoryLists.Next(node); + m_memoryLists.Unlink( m_lockList, node ); + m_memoryLists[node].lockCount = 0; + destroyList.AddToTail( GetForFreeByIndex( node ) ); + node = nextNode; + } + + m_listsAreFreed = false; + Unlock(); + + for ( int i = 0; i < nFlush; i++ ) + { + DestroyResourceStorage( destroyList[i] ); + } + + return result; +} + +unsigned int CDataManagerBase::Purge( unsigned int nBytesToPurge ) +{ + unsigned int nTargetSize = MemUsed_Inline() - nBytesToPurge; + if ( nTargetSize < 0 ) + nTargetSize = 0; + unsigned int nImpliedCapacity = MemTotal_Inline() - nTargetSize; + return EnsureCapacity( nImpliedCapacity ); +} + + +void CDataManagerBase::DestroyResource( memhandle_t handle ) +{ + Lock(); + unsigned short index = FromHandle( handle ); + if ( !m_memoryLists.IsValidIndex(index) ) + { + Unlock(); + return; + } + + Assert( m_memoryLists[index].lockCount == 0 ); + if ( m_memoryLists[index].lockCount ) + BreakLock( handle ); + m_memoryLists.Unlink( m_lruList, index ); + void *p = GetForFreeByIndex( index ); + Unlock(); + + DestroyResourceStorage( p ); +} + + +void *CDataManagerBase::LockResource( memhandle_t handle ) +{ + AUTO_LOCK_DM(); + unsigned short memoryIndex = FromHandle(handle); + if ( memoryIndex != m_memoryLists.InvalidIndex() ) + { + if ( m_memoryLists[memoryIndex].lockCount == 0 ) + { + m_memoryLists.Unlink( m_lruList, memoryIndex ); + m_memoryLists.LinkToTail( m_lockList, memoryIndex ); + } + Assert(m_memoryLists[memoryIndex].lockCount != (unsigned short)-1); + m_memoryLists[memoryIndex].lockCount++; + return m_memoryLists[memoryIndex].pStore; + } + + return NULL; +} + +int CDataManagerBase::UnlockResource( memhandle_t handle ) +{ + AUTO_LOCK_DM(); + unsigned short memoryIndex = FromHandle(handle); + if ( memoryIndex != m_memoryLists.InvalidIndex() ) + { + Assert( m_memoryLists[memoryIndex].lockCount > 0 ); + if ( m_memoryLists[memoryIndex].lockCount > 0 ) + { + m_memoryLists[memoryIndex].lockCount--; + if ( m_memoryLists[memoryIndex].lockCount == 0 ) + { + m_memoryLists.Unlink( m_lockList, memoryIndex ); + m_memoryLists.LinkToTail( m_lruList, memoryIndex ); + } + } + return m_memoryLists[memoryIndex].lockCount; + } + + return 0; +} + +void *CDataManagerBase::GetResource_NoLockNoLRUTouch( memhandle_t handle ) +{ + AUTO_LOCK_DM(); + unsigned short memoryIndex = FromHandle(handle); + if ( memoryIndex != m_memoryLists.InvalidIndex() ) + { + return m_memoryLists[memoryIndex].pStore; + } + return NULL; +} + + +void *CDataManagerBase::GetResource_NoLock( memhandle_t handle ) +{ + AUTO_LOCK_DM(); + unsigned short memoryIndex = FromHandle(handle); + if ( memoryIndex != m_memoryLists.InvalidIndex() ) + { + TouchByIndex( memoryIndex ); + return m_memoryLists[memoryIndex].pStore; + } + return NULL; +} + +void CDataManagerBase::TouchResource( memhandle_t handle ) +{ + AUTO_LOCK_DM(); + TouchByIndex( FromHandle(handle) ); +} + +void CDataManagerBase::MarkAsStale( memhandle_t handle ) +{ + AUTO_LOCK_DM(); + unsigned short memoryIndex = FromHandle(handle); + if ( memoryIndex != m_memoryLists.InvalidIndex() ) + { + if ( m_memoryLists[memoryIndex].lockCount == 0 ) + { + m_memoryLists.Unlink( m_lruList, memoryIndex ); + m_memoryLists.LinkToHead( m_lruList, memoryIndex ); + } + } +} + +int CDataManagerBase::BreakLock( memhandle_t handle ) +{ + AUTO_LOCK_DM(); + unsigned short memoryIndex = FromHandle(handle); + if ( memoryIndex != m_memoryLists.InvalidIndex() && m_memoryLists[memoryIndex].lockCount ) + { + int nBroken = m_memoryLists[memoryIndex].lockCount; + m_memoryLists[memoryIndex].lockCount = 0; + m_memoryLists.Unlink( m_lockList, memoryIndex ); + m_memoryLists.LinkToTail( m_lruList, memoryIndex ); + + return nBroken; + } + return 0; +} + +int CDataManagerBase::BreakAllLocks() +{ + AUTO_LOCK_DM(); + int nBroken = 0; + int node; + int nextNode; + + node = m_memoryLists.Head(m_lockList); + while ( node != m_memoryLists.InvalidIndex() ) + { + nBroken++; + nextNode = m_memoryLists.Next(node); + m_memoryLists[node].lockCount = 0; + m_memoryLists.Unlink( m_lockList, node ); + m_memoryLists.LinkToTail( m_lruList, node ); + node = nextNode; + } + + return nBroken; + +} + +unsigned short CDataManagerBase::CreateHandle( bool bCreateLocked ) +{ + AUTO_LOCK_DM(); + int memoryIndex = m_memoryLists.Head(m_freeList); + unsigned short list = ( bCreateLocked ) ? m_lockList : m_lruList; + if ( memoryIndex != m_memoryLists.InvalidIndex() ) + { + m_memoryLists.Unlink( m_freeList, memoryIndex ); + m_memoryLists.LinkToTail( list, memoryIndex ); + } + else + { + memoryIndex = m_memoryLists.AddToTail( list ); + } + + if ( bCreateLocked ) + { + m_memoryLists[memoryIndex].lockCount++; + } + + return memoryIndex; +} + +memhandle_t CDataManagerBase::StoreResourceInHandle( unsigned short memoryIndex, void *pStore, unsigned int realSize ) +{ + AUTO_LOCK_DM(); + resource_lru_element_t &mem = m_memoryLists[memoryIndex]; + mem.pStore = pStore; + m_memUsed += realSize; + return ToHandle(memoryIndex); +} + +void CDataManagerBase::TouchByIndex( unsigned short memoryIndex ) +{ + if ( memoryIndex != m_memoryLists.InvalidIndex() ) + { + if ( m_memoryLists[memoryIndex].lockCount == 0 ) + { + m_memoryLists.Unlink( m_lruList, memoryIndex ); + m_memoryLists.LinkToTail( m_lruList, memoryIndex ); + } + } +} + +memhandle_t CDataManagerBase::ToHandle( unsigned short index ) +{ + unsigned int hiword = m_memoryLists.Element(index).serial; + hiword <<= 16; + index++; + return (memhandle_t)( hiword|index ); +} + +unsigned int CDataManagerBase::TargetSize() +{ + return MemTotal_Inline(); +} + +unsigned int CDataManagerBase::AvailableSize() +{ + return MemAvailable_Inline(); +} + + +unsigned int CDataManagerBase::UsedSize() +{ + return MemUsed_Inline(); +} + +// free resources until there is enough space to hold "size" +unsigned int CDataManagerBase::EnsureCapacity( unsigned int size ) +{ + unsigned nBytesInitial = MemUsed_Inline(); + while ( MemUsed_Inline() > MemTotal_Inline() || MemAvailable_Inline() < size ) + { + Lock(); + int lruIndex = m_memoryLists.Head( m_lruList ); + if ( lruIndex == m_memoryLists.InvalidIndex() ) + { + Unlock(); + break; + } + m_memoryLists.Unlink( m_lruList, lruIndex ); + void *p = GetForFreeByIndex( lruIndex ); + Unlock(); + DestroyResourceStorage( p ); + } + return ( nBytesInitial - MemUsed_Inline() ); +} + +// free this resource and move the handle to the free list +void *CDataManagerBase::GetForFreeByIndex( unsigned short memoryIndex ) +{ + void *p = NULL; + if ( memoryIndex != m_memoryLists.InvalidIndex() ) + { + Assert( m_memoryLists[memoryIndex].lockCount == 0 ); + + resource_lru_element_t &mem = m_memoryLists[memoryIndex]; + unsigned size = GetRealSize( mem.pStore ); + if ( size > m_memUsed ) + { + ExecuteOnce( Warning( "Data manager 'used' memory incorrect\n" ) ); + size = m_memUsed; + } + m_memUsed -= size; + p = mem.pStore; + mem.pStore = NULL; + mem.serial++; + m_memoryLists.LinkToTail( m_freeList, memoryIndex ); + } + return p; +} + +// get a list of everything in the LRU +void CDataManagerBase::GetLRUHandleList( CUtlVector< memhandle_t >& list ) +{ + for ( int node = m_memoryLists.Tail(m_lruList); + node != m_memoryLists.InvalidIndex(); + node = m_memoryLists.Previous(node) ) + { + list.AddToTail( ToHandle( node ) ); + } +} + +// get a list of everything locked +void CDataManagerBase::GetLockHandleList( CUtlVector< memhandle_t >& list ) +{ + for ( int node = m_memoryLists.Head(m_lockList); + node != m_memoryLists.InvalidIndex(); + node = m_memoryLists.Next(node) ) + { + list.AddToTail( ToHandle( node ) ); + } +} + diff --git a/tier1/diff.cpp b/tier1/diff.cpp new file mode 100644 index 00000000..08c4e8f7 --- /dev/null +++ b/tier1/diff.cpp @@ -0,0 +1,547 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "tier0/platform.h" +#include "tier0/dbg.h" +#include "tier1/diff.h" +#include "mathlib/mathlib.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +// format of diff output: +// 0NN (N=1..127) copy next N literaly +// +// 1NN (N=1..127) ofs (-128..127) copy next N bytes from original, changin offset by N bytes from +// last copy end +// 100 N ofs(-32768..32767) copy next N, with larger delta offset +// 00 NNNN(1..65535) ofs(-32768..32767) big copy from old +// 80 00 NN NN NN big raw copy +// +// available codes (could be used for additonal compression ops) +// long offset form whose offset could have fit in short offset + +// note - this algorithm uses storage equal to 8* the old buffer size. 64k=.5mb + + +#define MIN_MATCH_LEN 8 +#define ACCEPTABLE_MATCH_LEN 4096 + +struct BlockPtr +{ + BlockPtr *Next; + uint8 const *dataptr; +}; + +template static inline void AddToHead(T * & head, V * node) +{ + node->Next=head; + head=node; +} + +void Fail(char const *msg) +{ + Assert(0); +} + +void ApplyDiffs(uint8 const *OldBlock, uint8 const *DiffList, + int OldSize, int DiffListSize, int &ResultListSize,uint8 *Output,uint32 OutSize) +{ + uint8 const *copy_src=OldBlock; + uint8 const *end_of_diff_list=DiffList+DiffListSize; + uint8 const *obuf=Output; + while(DiffList32767) + copy_ofs|=0xffff0000; + // printf("long cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz); + + memcpy(Output,copy_src+copy_ofs,copy_sz); + Output+=copy_sz; + copy_src=copy_src+copy_ofs+copy_sz; + DiffList+=4; + } + else + { + if (op & 0x80) + { + int copy_sz=op & 0x7f; + int copy_ofs; + if (copy_sz==0) + { + copy_sz=DiffList[0]; + if (copy_sz==0) + { + // big raw copy + copy_sz=DiffList[1]+256*DiffList[2]+65536*DiffList[3]; + memcpy(Output,DiffList+4,copy_sz); + // printf("big rawcopy to %x len=%d\n", Output-obuf,copy_sz); + + DiffList+=copy_sz+4; + Output+=copy_sz; + } + else + { + copy_ofs=DiffList[1]+(DiffList[2]*256); + if (copy_ofs>32767) + copy_ofs|=0xffff0000; + // printf("long ofs cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz); + + memcpy(Output,copy_src+copy_ofs,copy_sz); + Output+=copy_sz; + copy_src=copy_src+copy_ofs+copy_sz; + DiffList+=3; + } + } + else + { + copy_ofs=DiffList[0]; + if (copy_ofs>127) + copy_ofs|=0xffffff80; + // printf("cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz); + + memcpy(Output,copy_src+copy_ofs,copy_sz); + Output+=copy_sz; + copy_src=copy_src+copy_ofs+copy_sz; + DiffList++; + } + } + else + { + // printf("raw copy %d to %x\n",op & 127,Output-obuf); + memcpy(Output,DiffList,op & 127); + Output+=op & 127; + DiffList+=(op & 127); + } + } + } + ResultListSize=Output-obuf; + +} + +static void CopyPending(int len, uint8 const *rawbytes,uint8 * &outbuf, uint8 const *limit) +{ +// printf("copy raw len=%d\n",len); + if (len<128) + { + if (limit-outbuf < len+1) + Fail("diff buffer overrun"); + *(outbuf++)=len; + memcpy(outbuf,rawbytes,len); + outbuf+=len; + } + else + { + if (limit-outbuf < len+5) + Fail("diff buffer overrun"); + *(outbuf++)=0x80; + *(outbuf++)=0x00; + *(outbuf++)=(len & 255); + *(outbuf++)=((len>>8) & 255); + *(outbuf++)=((len>>16) & 255); + memcpy(outbuf,rawbytes,len); + outbuf+=len; + } +} + +static uint32 hasher(uint8 const *mdata) +{ + // attempt to scramble the bits of h1 and h2 together + uint32 ret=0; + for(int i=0;idataptr=walk; + AddToHead(HashedMatches[hash1],newnode); + walk++; + } + else + ret=1; + // now, we have the hash table which may be used to search. begin the output step + int pending_raw_len=0; + walk=NewBlock; + uint8 *outbuf=Output; + uint8 const *lastmatchend=OldBlock; + while(walkMIN_MATCH_LEN, take it + for(BlockPtr *b=HashedMatches[hash1];b;b=b->Next) + { + // find the match length + int match_of=b->dataptr-lastmatchend; + if ((match_of>-32768) && (match_of<32767)) + { + int max_mlength=MIN(65535,OldBlock+OldSize-b->dataptr); + max_mlength=MIN(max_mlength,NewBlock+NewSize-walk); + int i; + for(i=0;idataptr[i]) + break; + if ((i>MIN_MATCH_LEN) && (i>longest)) + { + longest=i; + longest_block=b; + if (longest>ACCEPTABLE_MATCH_LEN) + break; + } + } + } + } + // now, we have a match maybe + if (longest_block) + { + if (pending_raw_len) // must output + { + ret=1; + CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize); + pending_raw_len=0; + } + // now, output copy block + int match_of=longest_block->dataptr-lastmatchend; + int nremaining=OutSize-(outbuf-Output); + + if (match_of) + ret=1; +// printf("copy from %x to %x len=%d\n", match_of,outbuf-Output,longest); + if (longest>127) + { + // use really long encoding + if (nremaining<5) + Fail("diff buff needs increase"); + *(outbuf++)=00; + *(outbuf++)=(longest & 255); + *(outbuf++)=((longest>>8) & 255); + *(outbuf++)=(match_of & 255); + *(outbuf++)=((match_of>>8) & 255); + + } + else + { + if ((match_of>=-128) && (match_of<128)) + { + if (nremaining<2) + Fail("diff buff needs increase"); + *(outbuf++)=128+longest; + *(outbuf++)=(match_of&255); + } + else + { + // use long encoding + if (nremaining<4) + Fail("diff buff needs increase"); + *(outbuf++)=0x80; + *(outbuf++)=longest; + *(outbuf++)=(match_of & 255); + *(outbuf++)=((match_of>>8) & 255); + } + } + lastmatchend=longest_block->dataptr+longest; + walk+=longest; + } + else + { + walk++; + pending_raw_len++; + } + } + // now, flush pending raw copy + if (pending_raw_len) // must output + { + ret=1; + CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize); + pending_raw_len=0; + } + delete[] HashedMatches; + if (Blocks) + delete[] Blocks; + DiffListSize=outbuf-Output; + return ret; +} + + +int FindDiffs(uint8 const *NewBlock, uint8 const *OldBlock, + int NewSize, int OldSize, int &DiffListSize,uint8 *Output,uint32 OutSize) +{ + + int ret=0; + if (OldSize!=NewSize) + ret=1; + // first, build the hash table + BlockPtr *HashedMatches[65536]; + memset(HashedMatches,0,sizeof(HashedMatches)); + BlockPtr *Blocks=0; + if (OldSize) + Blocks=new BlockPtr[OldSize]; + BlockPtr *FreeList=Blocks; + // now, build the hash table + uint8 const *walk=OldBlock; + if (OldBlock && OldSize) + while(walkdataptr=walk; + AddToHead(HashedMatches[hash1],newnode); + walk++; + } + else + ret=1; + // now, we have the hash table which may be used to search. begin the output step + int pending_raw_len=0; + walk=NewBlock; + uint8 *outbuf=Output; + uint8 const *lastmatchend=OldBlock; + while(walkMIN_MATCH_LEN, take it + for(BlockPtr *b=HashedMatches[hash1];b;b=b->Next) + { + // find the match length + int match_of=b->dataptr-lastmatchend; + if ((match_of>-32768) && (match_of<32767)) + { + int max_mlength=MIN(65535,OldBlock+OldSize-b->dataptr); + max_mlength=MIN(max_mlength,NewBlock+NewSize-walk); + int i; + for(i=0;idataptr[i]) + break; + if ((i>MIN_MATCH_LEN) && (i>longest)) + { + longest=i; + longest_block=b; + } + } + } + } + // now, we have a match maybe + if (longest_block) + { + if (pending_raw_len) // must output + { + ret=1; + CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize); + pending_raw_len=0; + } + // now, output copy block + int match_of=longest_block->dataptr-lastmatchend; + int nremaining=OutSize-(outbuf-Output); + if (match_of) + ret=1; + if (longest>127) + { + // use really long encoding + if (nremaining<5) + Fail("diff buff needs increase"); + *(outbuf++)=00; + *(outbuf++)=(longest & 255); + *(outbuf++)=((longest>>8) & 255); + *(outbuf++)=(match_of & 255); + *(outbuf++)=((match_of>>8) & 255); + } + else + { + if ((match_of>=-128) && (match_of<128)) + { + if (nremaining<2) + Fail("diff buff needs increase"); + *(outbuf++)=128+longest; + *(outbuf++)=(match_of&255); + } + else + { + // use long encoding + if (nremaining<4) + Fail("diff buff needs increase"); + *(outbuf++)=0x80; + *(outbuf++)=longest; + *(outbuf++)=(match_of & 255); + *(outbuf++)=((match_of>>8) & 255); + } + } + lastmatchend=longest_block->dataptr+longest; + walk+=longest; + } + else + { + walk++; + pending_raw_len++; + } + } + // now, flush pending raw copy + if (pending_raw_len) // must output + { + ret=1; + CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize); + pending_raw_len=0; + } + if (Blocks) + delete[] Blocks; + DiffListSize=outbuf-Output; + return ret; +} + + +int FindDiffsLowMemory(uint8 const *NewBlock, uint8 const *OldBlock, + int NewSize, int OldSize, int &DiffListSize,uint8 *Output,uint32 OutSize) +{ + + int ret=0; + if (OldSize!=NewSize) + ret=1; + uint8 const *old_data_hash[256]; + memset(old_data_hash,0,sizeof(old_data_hash)); + int pending_raw_len=0; + uint8 const *walk=NewBlock; + uint8 const *oldptr=OldBlock; + uint8 *outbuf=Output; + uint8 const *lastmatchend=OldBlock; + while(walkMIN_MATCH_LEN) + { + longest_block=old_data_hash[hash1]; + longest=nmatches; + } + } + } + // now, we have a match maybe + if (longest_block) + { + if (pending_raw_len) // must output + { + ret=1; + CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize); + pending_raw_len=0; + } + // now, output copy block + int match_of=longest_block-lastmatchend; + int nremaining=OutSize-(outbuf-Output); + if (match_of) + ret=1; + if (longest>127) + { + // use really long encoding + if (nremaining<5) + Fail("diff buff needs increase"); + *(outbuf++)=00; + *(outbuf++)=(longest & 255); + *(outbuf++)=((longest>>8) & 255); + *(outbuf++)=(match_of & 255); + *(outbuf++)=((match_of>>8) & 255); + } + else + { + if ((match_of>=-128) && (match_of<128)) + { + if (nremaining<2) + Fail("diff buff needs increase"); + *(outbuf++)=128+longest; + *(outbuf++)=(match_of&255); + } + else + { + // use long encoding + if (nremaining<4) + Fail("diff buff needs increase"); + *(outbuf++)=0x80; + *(outbuf++)=longest; + *(outbuf++)=(match_of & 255); + *(outbuf++)=((match_of>>8) & 255); + } + } + lastmatchend=longest_block+longest; + walk+=longest; + } + else + { + walk++; + pending_raw_len++; + } + } + // now, flush pending raw copy + if (pending_raw_len) // must output + { + ret=1; + CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize); + pending_raw_len=0; + } + DiffListSize=outbuf-Output; + return ret; +} + + diff --git a/tier1/generichash.cpp b/tier1/generichash.cpp new file mode 100644 index 00000000..f3e71e34 --- /dev/null +++ b/tier1/generichash.cpp @@ -0,0 +1,303 @@ +//======= Copyright © 2005, , Valve Corporation, All rights reserved. ========= +// +// Purpose: Variant Pearson Hash general purpose hashing algorithm described +// by Cargill in C++ Report 1994. Generates a 16-bit result. +// +//============================================================================= + +#include +#include "tier0/basetypes.h" +#include "tier0/platform.h" +#include "generichash.h" +#include + +//----------------------------------------------------------------------------- +// +// Table of randomly shuffled values from 0-255 generated by: +// +//----------------------------------------------------------------------------- +/* +void MakeRandomValues() +{ + int i, j, r; + unsigned t; + srand( 0xdeadbeef ); + + for ( i = 0; i < 256; i++ ) + { + g_nRandomValues[i] = (unsigned )i; + } + + for (j = 0; j < 8; j++) + { + for (i = 0; i < 256; i++) + { + r = rand() & 0xff; + t = g_nRandomValues[i]; + g_nRandomValues[i] = g_nRandomValues[r]; + g_nRandomValues[r] = t; + } + } + + printf("static unsigned g_nRandomValues[256] =\n{\n"); + + for (i = 0; i < 256; i += 16) + { + printf("\t"); + for (j = 0; j < 16; j++) + printf(" %3d,", g_nRandomValues[i+j]); + printf("\n"); + } + printf("};\n"); +} +*/ + +static unsigned g_nRandomValues[256] = +{ + 238, 164, 191, 168, 115, 16, 142, 11, 213, 214, 57, 151, 248, 252, 26, 198, + 13, 105, 102, 25, 43, 42, 227, 107, 210, 251, 86, 66, 83, 193, 126, 108, + 131, 3, 64, 186, 192, 81, 37, 158, 39, 244, 14, 254, 75, 30, 2, 88, + 172, 176, 255, 69, 0, 45, 116, 139, 23, 65, 183, 148, 33, 46, 203, 20, + 143, 205, 60, 197, 118, 9, 171, 51, 233, 135, 220, 49, 71, 184, 82, 109, + 36, 161, 169, 150, 63, 96, 173, 125, 113, 67, 224, 78, 232, 215, 35, 219, + 79, 181, 41, 229, 149, 153, 111, 217, 21, 72, 120, 163, 133, 40, 122, 140, + 208, 231, 211, 200, 160, 182, 104, 110, 178, 237, 15, 101, 27, 50, 24, 189, + 177, 130, 187, 92, 253, 136, 100, 212, 19, 174, 70, 22, 170, 206, 162, 74, + 247, 5, 47, 32, 179, 117, 132, 195, 124, 123, 245, 128, 236, 223, 12, 84, + 54, 218, 146, 228, 157, 94, 106, 31, 17, 29, 194, 34, 56, 134, 239, 246, + 241, 216, 127, 98, 7, 204, 154, 152, 209, 188, 48, 61, 87, 97, 225, 85, + 90, 167, 155, 112, 145, 114, 141, 93, 250, 4, 201, 156, 38, 89, 226, 196, + 1, 235, 44, 180, 159, 121, 119, 166, 190, 144, 10, 91, 76, 230, 221, 80, + 207, 55, 58, 53, 175, 8, 6, 52, 68, 242, 18, 222, 103, 249, 147, 129, + 138, 243, 28, 185, 62, 59, 240, 202, 234, 99, 77, 73, 199, 137, 95, 165, +}; + +//----------------------------------------------------------------------------- +// String +//----------------------------------------------------------------------------- +unsigned FASTCALL HashString( const char *pszKey ) +{ + const uint8 *k = (const uint8 *)pszKey; + unsigned even = 0, + odd = 0, + n; + + while ((n = *k++) != 0) + { + even = g_nRandomValues[odd ^ n]; + if ((n = *k++) != 0) + odd = g_nRandomValues[even ^ n]; + else + break; + } + + return (even << 8) | odd ; +} + + +//----------------------------------------------------------------------------- +// Case-insensitive string +//----------------------------------------------------------------------------- +unsigned FASTCALL HashStringCaseless( const char *pszKey ) +{ + const uint8 *k = (const uint8 *) pszKey; + unsigned even = 0, + odd = 0, + n; + + while ((n = toupper(*k++)) != 0) + { + even = g_nRandomValues[odd ^ n]; + if ((n = toupper(*k++)) != 0) + odd = g_nRandomValues[even ^ n]; + else + break; + } + + return (even << 8) | odd; +} + +//----------------------------------------------------------------------------- +// 32 bit conventional case-insensitive string +//----------------------------------------------------------------------------- +unsigned FASTCALL HashStringCaselessConventional( const char *pszKey ) +{ + unsigned hash = 0xAAAAAAAA; // Alternating 1's and 0's to maximize the effect of the later multiply and add + + for( ; *pszKey ; pszKey++ ) + { + hash = ( ( hash << 5 ) + hash ) + (uint8)tolower(*pszKey); + } + + return hash; +} + +//----------------------------------------------------------------------------- +// int hash +//----------------------------------------------------------------------------- +unsigned FASTCALL HashInt( const int n ) +{ + register unsigned even, odd; + even = g_nRandomValues[n & 0xff]; + odd = g_nRandomValues[((n >> 8) & 0xff)]; + + even = g_nRandomValues[odd ^ (n >> 24)]; + odd = g_nRandomValues[even ^ (n >> 16) & 0xff]; + even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; + odd = g_nRandomValues[even ^ (n & 0xff)]; + + return (even << 8) | odd; +} + +//----------------------------------------------------------------------------- +// 4-byte hash +//----------------------------------------------------------------------------- +unsigned FASTCALL Hash4( const void *pKey ) +{ + register const uint32 * p = (const uint32 *) pKey; + register unsigned even, + odd, + n; + n = *p; + even = g_nRandomValues[n & 0xff]; + odd = g_nRandomValues[((n >> 8) & 0xff)]; + + even = g_nRandomValues[odd ^ (n >> 24)]; + odd = g_nRandomValues[even ^ (n >> 16) & 0xff]; + even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; + odd = g_nRandomValues[even ^ (n & 0xff)]; + + return (even << 8) | odd; +} + + +//----------------------------------------------------------------------------- +// 8-byte hash +//----------------------------------------------------------------------------- +unsigned FASTCALL Hash8( const void *pKey ) +{ + register const uint32 * p = (const uint32 *) pKey; + register unsigned even, + odd, + n; + n = *p; + even = g_nRandomValues[n & 0xff]; + odd = g_nRandomValues[((n >> 8) & 0xff)]; + + even = g_nRandomValues[odd ^ (n >> 24)]; + odd = g_nRandomValues[even ^ (n >> 16) & 0xff]; + even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; + odd = g_nRandomValues[even ^ (n & 0xff)]; + + n = *(p+1); + even = g_nRandomValues[odd ^ (n >> 24)]; + odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)]; + even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; + odd = g_nRandomValues[even ^ (n & 0xff)]; + + return (even << 8) | odd; +} + + +//----------------------------------------------------------------------------- +// 12-byte hash +//----------------------------------------------------------------------------- +unsigned FASTCALL Hash12( const void *pKey ) +{ + register const uint32 * p = (const uint32 *) pKey; + register unsigned even, + odd, + n; + n = *p; + even = g_nRandomValues[n & 0xff]; + odd = g_nRandomValues[((n >> 8) & 0xff)]; + + even = g_nRandomValues[odd ^ (n >> 24)]; + odd = g_nRandomValues[even ^ (n >> 16) & 0xff]; + even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; + odd = g_nRandomValues[even ^ (n & 0xff)]; + + n = *(p+1); + even = g_nRandomValues[odd ^ (n >> 24)]; + odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)]; + even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; + odd = g_nRandomValues[even ^ (n & 0xff)]; + + n = *(p+2); + even = g_nRandomValues[odd ^ (n >> 24)]; + odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)]; + even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; + odd = g_nRandomValues[even ^ (n & 0xff)]; + + return (even << 8) | odd; +} + + +//----------------------------------------------------------------------------- +// 16-byte hash +//----------------------------------------------------------------------------- +unsigned FASTCALL Hash16( const void *pKey ) +{ + register const uint32 * p = (const uint32 *) pKey; + register unsigned even, + odd, + n; + n = *p; + even = g_nRandomValues[n & 0xff]; + odd = g_nRandomValues[((n >> 8) & 0xff)]; + + even = g_nRandomValues[odd ^ (n >> 24)]; + odd = g_nRandomValues[even ^ (n >> 16) & 0xff]; + even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; + odd = g_nRandomValues[even ^ (n & 0xff)]; + + n = *(p+1); + even = g_nRandomValues[odd ^ (n >> 24)]; + odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)]; + even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; + odd = g_nRandomValues[even ^ (n & 0xff)]; + + n = *(p+2); + even = g_nRandomValues[odd ^ (n >> 24)]; + odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)]; + even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; + odd = g_nRandomValues[even ^ (n & 0xff)]; + + n = *(p+3); + even = g_nRandomValues[odd ^ (n >> 24)]; + odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)]; + even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; + odd = g_nRandomValues[even ^ (n & 0xff)]; + + return (even << 8) | odd; +} + + +//----------------------------------------------------------------------------- +// Arbitrary fixed length hash +//----------------------------------------------------------------------------- +unsigned FASTCALL HashBlock( const void *pKey, unsigned size ) +{ + const uint8 * k = (const uint8 *) pKey; + unsigned even = 0, + odd = 0, + n; + + while (size) + { + --size; + n = *k++; + even = g_nRandomValues[odd ^ n]; + if (size) + { + --size; + n = *k++; + odd = g_nRandomValues[even ^ n]; + } + else + break; + } + + return (even << 8) | odd; +} + diff --git a/tier1/interface.cpp b/tier1/interface.cpp new file mode 100644 index 00000000..997ce0cc --- /dev/null +++ b/tier1/interface.cpp @@ -0,0 +1,465 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// +#if defined( _WIN32 ) && !defined( _X360 ) +#include +#endif + +#if !defined( DONT_PROTECT_FILEIO_FUNCTIONS ) +#define DONT_PROTECT_FILEIO_FUNCTIONS // for protected_things.h +#endif + +#if defined( PROTECTED_THINGS_ENABLE ) +#undef PROTECTED_THINGS_ENABLE // from protected_things.h +#endif + +#include +#include "interface.h" +#include "basetypes.h" +#include "tier0/dbg.h" +#include +#include +#include "tier1/strtools.h" +#include "tier0/icommandline.h" +#include "tier0/dbg.h" +#include "tier0/threadtools.h" +#ifdef _WIN32 +#include // getcwd +#elif defined _LINUX || defined __APPLE__ +#define _getcwd getcwd +#endif +#if defined( _X360 ) +#include "xbox/xbox_win32stubs.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// ------------------------------------------------------------------------------------ // +// InterfaceReg. +// ------------------------------------------------------------------------------------ // +InterfaceReg *InterfaceReg::s_pInterfaceRegs = NULL; + +InterfaceReg::InterfaceReg( InstantiateInterfaceFn fn, const char *pName ) : + m_pName(pName) +{ + m_CreateFn = fn; + m_pNext = s_pInterfaceRegs; + s_pInterfaceRegs = this; +} + +// ------------------------------------------------------------------------------------ // +// CreateInterface. +// This is the primary exported function by a dll, referenced by name via dynamic binding +// that exposes an opqaue function pointer to the interface. +// ------------------------------------------------------------------------------------ // +void* CreateInterface( const char *pName, int *pReturnCode ) +{ + InterfaceReg *pCur; + + for (pCur=InterfaceReg::s_pInterfaceRegs; pCur; pCur=pCur->m_pNext) + { + if (strcmp(pCur->m_pName, pName) == 0) + { + if (pReturnCode) + { + *pReturnCode = IFACE_OK; + } + return pCur->m_CreateFn(); + } + } + + if (pReturnCode) + { + *pReturnCode = IFACE_FAILED; + } + return NULL; +} + + +#if defined _LINUX || defined __APPLE__ +// Linux doesn't have this function so this emulates its functionality +void *GetModuleHandle(const char *name) +{ + void *handle; + + if( name == NULL ) + { + // hmm, how can this be handled under linux.... + // is it even needed? + return NULL; + } + + if( (handle=dlopen(name, RTLD_NOW))==NULL) + { + printf("DLOPEN Error:%s\n",dlerror()); + // couldn't open this file + return NULL; + } + + // read "man dlopen" for details + // in short dlopen() inc a ref count + // so dec the ref count by performing the close + dlclose(handle); + return handle; +} +#endif + +#if defined( _WIN32 ) && !defined( _X360 ) +#define WIN32_LEAN_AND_MEAN +#include "windows.h" +#endif + +//----------------------------------------------------------------------------- +// Purpose: returns a pointer to a function, given a module +// Input : pModuleName - module name +// *pName - proc name +//----------------------------------------------------------------------------- +static void *Sys_GetProcAddress( const char *pModuleName, const char *pName ) +{ + HMODULE hModule = GetModuleHandle( pModuleName ); + return GetProcAddress( hModule, pName ); +} + +static void *Sys_GetProcAddress( HMODULE hModule, const char *pName ) +{ + return GetProcAddress( hModule, pName ); +} + +bool Sys_IsDebuggerPresent() +{ + return Plat_IsInDebugSession(); +} + +struct ThreadedLoadLibaryContext_t +{ + const char *m_pLibraryName; + HMODULE m_hLibrary; +}; + +#ifdef _WIN32 + +// wraps LoadLibraryEx() since 360 doesn't support that +static HMODULE InternalLoadLibrary( const char *pName ) +{ +#if defined(_X360) + return LoadLibrary( pName ); +#else + return LoadLibraryEx( pName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); +#endif +} +unsigned ThreadedLoadLibraryFunc( void *pParam ) +{ + ThreadedLoadLibaryContext_t *pContext = (ThreadedLoadLibaryContext_t*)pParam; + pContext->m_hLibrary = InternalLoadLibrary(pContext->m_pLibraryName); + return 0; +} +#endif + +HMODULE Sys_LoadLibrary( const char *pLibraryName ) +{ + char str[1024]; +#if defined( _WIN32 ) && !defined( _X360 ) + const char *pModuleExtension = ".dll"; + const char *pModuleAddition = pModuleExtension; +#elif defined( _X360 ) + const char *pModuleExtension = "_360.dll"; + const char *pModuleAddition = pModuleExtension; +#elif defined( _LINUX ) + const char *pModuleExtension = ".so"; + const char *pModuleAddition = "_i486.so"; // if an extension is on the filename assume the i486 binary set +#elif defined( __APPLE__ ) + const char *pModuleExtension = ".dylib"; + const char *pModuleAddition = ".dylib"; +#endif + Q_strncpy( str, pLibraryName, sizeof(str) ); + if ( !Q_stristr( str, pModuleExtension ) ) + { + if ( IsX360() ) + { + Q_StripExtension( str, str, sizeof(str) ); + } + Q_strncat( str, pModuleAddition, sizeof(str) ); + } + Q_FixSlashes( str ); + +#ifdef _WIN32 + ThreadedLoadLibraryFunc_t threadFunc = GetThreadedLoadLibraryFunc(); + if ( !threadFunc ) + return InternalLoadLibrary( str ); + + ThreadedLoadLibaryContext_t context; + context.m_pLibraryName = str; + context.m_hLibrary = 0; + + ThreadHandle_t h = CreateSimpleThread( ThreadedLoadLibraryFunc, &context ); + +#ifdef _X360 + ThreadSetAffinity( h, XBOX_PROCESSOR_3 ); +#endif + + unsigned int nTimeout = 0; + while( ThreadWaitForObject( h, true, nTimeout ) == TW_TIMEOUT ) + { + nTimeout = threadFunc(); + } + + ReleaseThreadHandle( h ); + return context.m_hLibrary; + +#elif defined _LINUX || defined __APPLE__ + HMODULE ret = dlopen( str, RTLD_NOW ); + if ( ! ret ) + { + const char *pError = dlerror(); + if ( pError && ( strstr( pError, "No such file" ) == 0 ) ) + { + Msg( " failed to dlopen %s error=%s\n", str, pError ); + + } + } + + return ret; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Loads a DLL/component from disk and returns a handle to it +// Input : *pModuleName - filename of the component +// Output : opaque handle to the module (hides system dependency) +//----------------------------------------------------------------------------- +CSysModule *Sys_LoadModule( const char *pModuleName ) +{ + // If using the Steam filesystem, either the DLL must be a minimum footprint + // file in the depot (MFP) or a filesystem GetLocalCopy() call must be made + // prior to the call to this routine. + char szCwd[1024]; + HMODULE hDLL = NULL; + + if ( !Q_IsAbsolutePath( pModuleName ) ) + { + // full path wasn't passed in, using the current working dir + _getcwd( szCwd, sizeof( szCwd ) ); + if ( IsX360() ) + { + int i = CommandLine()->FindParm( "-basedir" ); + if ( i ) + { + strcpy( szCwd, CommandLine()->GetParm( i+1 ) ); + } + } + if (szCwd[strlen(szCwd) - 1] == '/' || szCwd[strlen(szCwd) - 1] == '\\' ) + { + szCwd[strlen(szCwd) - 1] = 0; + } + + char szAbsoluteModuleName[1024]; + if ( strstr( pModuleName, "bin/") == pModuleName ) + { + // don't make bin/bin path + Q_snprintf( szAbsoluteModuleName, sizeof(szAbsoluteModuleName), "%s/%s", szCwd, pModuleName ); + } + else + { + Q_snprintf( szAbsoluteModuleName, sizeof(szAbsoluteModuleName), "%s/bin/%s", szCwd, pModuleName ); + } + hDLL = Sys_LoadLibrary( szAbsoluteModuleName ); + } + + if ( !hDLL ) + { + // full path failed, let LoadLibrary() try to search the PATH now + hDLL = Sys_LoadLibrary( pModuleName ); +#if defined( _DEBUG ) + if ( !hDLL ) + { +// So you can see what the error is in the debugger... +#if defined( _WIN32 ) && !defined( _X360 ) + char *lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + LocalFree( (HLOCAL)lpMsgBuf ); +#elif defined( _X360 ) + Msg( "Failed to load %s:\n", pModuleName ); +#else + Error( "Failed to load %s: %s\n", pModuleName, dlerror() ); +#endif // _WIN32 + } +#endif // DEBUG + } + + // If running in the debugger, assume debug binaries are okay, otherwise they must run with -allowdebug + if ( !IsX360() && hDLL && + !CommandLine()->FindParm( "-allowdebug" ) && + !Sys_IsDebuggerPresent() ) + { + if ( Sys_GetProcAddress( hDLL, "BuiltDebug" ) ) + { + Error( "Module %s is a debug build\n", pModuleName ); + } + } + + return reinterpret_cast(hDLL); +} + + +//----------------------------------------------------------------------------- +// Purpose: Unloads a DLL/component from +// Input : *pModuleName - filename of the component +// Output : opaque handle to the module (hides system dependency) +//----------------------------------------------------------------------------- +void Sys_UnloadModule( CSysModule *pModule ) +{ + if ( !pModule ) + return; + + HMODULE hDLL = reinterpret_cast(pModule); + +#ifdef _WIN32 + FreeLibrary( hDLL ); +#elif defined(_LINUX) || defined(__APPLE__) + dlclose((void *)hDLL); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: returns a pointer to a function, given a module +// Input : module - windows HMODULE from Sys_LoadModule() +// *pName - proc name +// Output : factory for this module +//----------------------------------------------------------------------------- +CreateInterfaceFn Sys_GetFactory( CSysModule *pModule ) +{ + if ( !pModule ) + return NULL; + + HMODULE hDLL = reinterpret_cast(pModule); +#ifdef _WIN32 + return reinterpret_cast(GetProcAddress( hDLL, CREATEINTERFACE_PROCNAME )); +#elif defined(_LINUX) || defined (__APPLE__) + // Linux gives this error: + //../public/interface.cpp: In function `IBaseInterface *(*Sys_GetFactory + //(CSysModule *)) (const char *, int *)': + //../public/interface.cpp:154: ISO C++ forbids casting between + //pointer-to-function and pointer-to-object + // + // so lets get around it :) + return (CreateInterfaceFn)(GetProcAddress( hDLL, CREATEINTERFACE_PROCNAME )); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: returns the instance of this module +// Output : interface_instance_t +//----------------------------------------------------------------------------- +CreateInterfaceFn Sys_GetFactoryThis( void ) +{ + return CreateInterface; +} + +//----------------------------------------------------------------------------- +// Purpose: returns the instance of the named module +// Input : *pModuleName - name of the module +// Output : interface_instance_t - instance of that module +//----------------------------------------------------------------------------- +CreateInterfaceFn Sys_GetFactory( const char *pModuleName ) +{ +#ifdef _WIN32 + return static_cast( Sys_GetProcAddress( pModuleName, CREATEINTERFACE_PROCNAME ) ); +#elif defined(_LINUX) || defined(__APPLE__) + // see Sys_GetFactory( CSysModule *pModule ) for an explanation + return (CreateInterfaceFn)( Sys_GetProcAddress( pModuleName, CREATEINTERFACE_PROCNAME ) ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: get the interface for the specified module and version +// Input : +// Output : +//----------------------------------------------------------------------------- +bool Sys_LoadInterface( + const char *pModuleName, + const char *pInterfaceVersionName, + CSysModule **pOutModule, + void **pOutInterface ) +{ + CSysModule *pMod = Sys_LoadModule( pModuleName ); + if ( !pMod ) + return false; + + CreateInterfaceFn fn = Sys_GetFactory( pMod ); + if ( !fn ) + { + Sys_UnloadModule( pMod ); + return false; + } + + *pOutInterface = fn( pInterfaceVersionName, NULL ); + if ( !( *pOutInterface ) ) + { + Sys_UnloadModule( pMod ); + return false; + } + + if ( pOutModule ) + *pOutModule = pMod; + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Place this as a singleton at module scope (e.g.) and use it to get the factory from the specified module name. +// +// When the singleton goes out of scope (.dll unload if at module scope), +// then it'll call Sys_UnloadModule on the module so that the refcount is decremented +// and the .dll actually can unload from memory. +//----------------------------------------------------------------------------- +CDllDemandLoader::CDllDemandLoader( char const *pchModuleName ) : + m_pchModuleName( pchModuleName ), + m_hModule( 0 ), + m_bLoadAttempted( false ) +{ +} + +CDllDemandLoader::~CDllDemandLoader() +{ + Unload(); +} + +CreateInterfaceFn CDllDemandLoader::GetFactory() +{ + if ( !m_hModule && !m_bLoadAttempted ) + { + m_bLoadAttempted = true; + m_hModule = Sys_LoadModule( m_pchModuleName ); + } + + if ( !m_hModule ) + { + return NULL; + } + + return Sys_GetFactory( m_hModule ); +} + +void CDllDemandLoader::Unload() +{ + if ( m_hModule ) + { + Sys_UnloadModule( m_hModule ); + m_hModule = 0; + } +} diff --git a/tier1/mempool.cpp b/tier1/mempool.cpp new file mode 100644 index 00000000..fe9bd640 --- /dev/null +++ b/tier1/mempool.cpp @@ -0,0 +1,317 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// + +#include "tier0/basetypes.h" +#include "mempool.h" +#include +#ifdef __APPLE__ +#include +#else +#include +#endif +#include +#include "tier0/dbg.h" +#include +#include "tier1/strtools.h" + +// Should be last include +#include "tier0/memdbgon.h" + +MemoryPoolReportFunc_t CMemoryPool::g_ReportFunc = 0; + +//----------------------------------------------------------------------------- +// Error reporting... (debug only) +//----------------------------------------------------------------------------- + +void CMemoryPool::SetErrorReportFunc( MemoryPoolReportFunc_t func ) +{ + g_ReportFunc = func; +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CMemoryPool::CMemoryPool( int blockSize, int numElements, int growMode, const char *pszAllocOwner, int nAlignment ) +{ +#ifdef _X360 + if( numElements > 0 && growMode != GROW_NONE ) + { + numElements = 1; + } +#endif + + m_nAlignment = ( nAlignment != 0 ) ? nAlignment : 1; + Assert( IsPowerOfTwo( m_nAlignment ) ); + m_BlockSize = blockSize < (int)sizeof(void*) ? sizeof(void*) : blockSize; + m_BlockSize = AlignValue( m_BlockSize, m_nAlignment ); + m_BlocksPerBlob = numElements; + m_PeakAlloc = 0; + m_GrowMode = growMode; + if ( !pszAllocOwner ) + { + pszAllocOwner = __FILE__; + } + m_pszAllocOwner = pszAllocOwner; + Init(); + AddNewBlob(); +} + +//----------------------------------------------------------------------------- +// Purpose: Frees the memory contained in the mempool, and invalidates it for +// any further use. +// Input : *memPool - the mempool to shutdown +//----------------------------------------------------------------------------- +CMemoryPool::~CMemoryPool() +{ + if (m_BlocksAllocated > 0) + { + ReportLeaks(); + } + Clear(); +} + + +//----------------------------------------------------------------------------- +// Resets the pool +//----------------------------------------------------------------------------- +void CMemoryPool::Init() +{ + m_NumBlobs = 0; + m_BlocksAllocated = 0; + m_pHeadOfFreeList = 0; + m_BlobHead.m_pNext = m_BlobHead.m_pPrev = &m_BlobHead; +} + + +//----------------------------------------------------------------------------- +// Frees everything +//----------------------------------------------------------------------------- +void CMemoryPool::Clear() +{ + // Free everything.. + CBlob *pNext; + for( CBlob *pCur = m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur = pNext ) + { + pNext = pCur->m_pNext; + free( pCur ); + } + Init(); +} + +//----------------------------------------------------------------------------- +// Purpose: Reports memory leaks +//----------------------------------------------------------------------------- + +void CMemoryPool::ReportLeaks() +{ + if (!g_ReportFunc) + return; + + g_ReportFunc("Memory leak: mempool blocks left in memory: %d\n", m_BlocksAllocated); + +#ifdef _DEBUG + // walk and destroy the free list so it doesn't intefere in the scan + while (m_pHeadOfFreeList != NULL) + { + void *next = *((void**)m_pHeadOfFreeList); + memset(m_pHeadOfFreeList, 0, m_BlockSize); + m_pHeadOfFreeList = next; + } + + g_ReportFunc("Dumping memory: \'"); + + for( CBlob *pCur=m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur=pCur->m_pNext ) + { + // scan the memory block and dump the leaks + char *scanPoint = (char *)pCur->m_Data; + char *scanEnd = pCur->m_Data + pCur->m_NumBytes; + bool needSpace = false; + + while (scanPoint < scanEnd) + { + // search for and dump any strings + if ((unsigned)(*scanPoint + 1) <= 256 && isprint(*scanPoint)) + { + g_ReportFunc("%c", *scanPoint); + needSpace = true; + } + else if (needSpace) + { + needSpace = false; + g_ReportFunc(" "); + } + + scanPoint++; + } + } + + g_ReportFunc("\'\n"); +#endif // _DEBUG +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMemoryPool::AddNewBlob() +{ + MEM_ALLOC_CREDIT_(m_pszAllocOwner); + + int sizeMultiplier; + + if( m_GrowMode == GROW_SLOW ) + { + sizeMultiplier = 1; + } + else + { + if ( m_GrowMode == GROW_NONE ) + { + // Can only have one allocation when we're in this mode + if( m_NumBlobs != 0 ) + { + Assert( !"CMemoryPool::AddNewBlob: mode == GROW_NONE" ); + return; + } + } + + // GROW_FAST and GROW_NONE use this. + sizeMultiplier = m_NumBlobs + 1; + } + + // maybe use something other than malloc? + int nElements = m_BlocksPerBlob * sizeMultiplier; + int blobSize = m_BlockSize * nElements; + CBlob *pBlob = (CBlob*)malloc( sizeof(CBlob) - 1 + blobSize + ( m_nAlignment - 1 ) ); + Assert( pBlob ); + + // Link it in at the end of the blob list. + pBlob->m_NumBytes = blobSize; + pBlob->m_pNext = &m_BlobHead; + pBlob->m_pPrev = pBlob->m_pNext->m_pPrev; + pBlob->m_pNext->m_pPrev = pBlob->m_pPrev->m_pNext = pBlob; + + // setup the free list + m_pHeadOfFreeList = AlignValue( pBlob->m_Data, m_nAlignment ); + Assert (m_pHeadOfFreeList); + + void **newBlob = (void**)m_pHeadOfFreeList; + for (int j = 0; j < nElements-1; j++) + { + newBlob[0] = (char*)newBlob + m_BlockSize; + newBlob = (void**)newBlob[0]; + } + + // null terminate list + newBlob[0] = NULL; + m_NumBlobs++; +} + + +void* CMemoryPool::Alloc() +{ + return Alloc( m_BlockSize ); +} + + +void* CMemoryPool::AllocZero() +{ + return AllocZero( m_BlockSize ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Allocs a single block of memory from the pool. +// Input : amount - +//----------------------------------------------------------------------------- +void *CMemoryPool::Alloc( size_t amount ) +{ + void *returnBlock; + + if ( amount > (unsigned int)m_BlockSize ) + return NULL; + + if( !m_pHeadOfFreeList ) + { + // returning NULL is fine in GROW_NONE + if( m_GrowMode == GROW_NONE ) + { + //Assert( !"CMemoryPool::Alloc: tried to make new blob with GROW_NONE" ); + return NULL; + } + + // overflow + AddNewBlob(); + + // still failure, error out + if( !m_pHeadOfFreeList ) + { + Assert( !"CMemoryPool::Alloc: ran out of memory" ); + return NULL; + } + } + m_BlocksAllocated++; + m_PeakAlloc = MAX(m_PeakAlloc, m_BlocksAllocated); + + returnBlock = m_pHeadOfFreeList; + + // move the pointer the next block + m_pHeadOfFreeList = *((void**)m_pHeadOfFreeList); + + return returnBlock; +} + +//----------------------------------------------------------------------------- +// Purpose: Allocs a single block of memory from the pool, zeroes the memory before returning +// Input : amount - +//----------------------------------------------------------------------------- +void *CMemoryPool::AllocZero( size_t amount ) +{ + void *mem = Alloc( amount ); + if ( mem ) + { + V_memset( mem, 0x00, amount ); + } + return mem; +} + +//----------------------------------------------------------------------------- +// Purpose: Frees a block of memory +// Input : *memBlock - the memory to free +//----------------------------------------------------------------------------- +void CMemoryPool::Free( void *memBlock ) +{ + if ( !memBlock ) + return; // trying to delete NULL pointer, ignore + +#ifdef _DEBUG + // check to see if the memory is from the allocated range + bool bOK = false; + for( CBlob *pCur=m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur=pCur->m_pNext ) + { + if (memBlock >= pCur->m_Data && (char*)memBlock < (pCur->m_Data + pCur->m_NumBytes)) + { + bOK = true; + } + } + Assert (bOK); +#endif // _DEBUG + +#ifdef _DEBUG + // invalidate the memory + memset( memBlock, 0xDD, m_BlockSize ); +#endif + + m_BlocksAllocated--; + + // make the block point to the first item in the list + *((void**)memBlock) = m_pHeadOfFreeList; + + // the list head is now the new block + m_pHeadOfFreeList = memBlock; +} + + diff --git a/tier1/memstack.cpp b/tier1/memstack.cpp new file mode 100644 index 00000000..77b0a60d --- /dev/null +++ b/tier1/memstack.cpp @@ -0,0 +1,300 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#if defined( _WIN32 ) && !defined( _X360 ) +#define WIN_32_LEAN_AND_MEAN +#include +#define VA_COMMIT_FLAGS MEM_COMMIT +#define VA_RESERVE_FLAGS MEM_RESERVE +#elif defined( _X360 ) +#define VA_COMMIT_FLAGS (MEM_COMMIT|MEM_NOZERO|MEM_LARGE_PAGES) +#define VA_RESERVE_FLAGS (MEM_RESERVE|MEM_LARGE_PAGES) +#endif + +#include "tier0/dbg.h" +#include "memstack.h" +#include "utlmap.h" +#include "tier0/memdbgon.h" + +#ifdef _WIN32 +#pragma warning(disable:4073) +#pragma init_seg(lib) +#endif + +//----------------------------------------------------------------------------- + +MEMALLOC_DEFINE_EXTERNAL_TRACKING(CMemoryStack); + +//----------------------------------------------------------------------------- + +CMemoryStack::CMemoryStack() + : m_pNextAlloc( NULL ), + m_pCommitLimit( NULL ), + m_pAllocLimit( NULL ), + m_pBase( NULL ), + m_maxSize( 0 ), +#if defined (_LINUX) || defined (__APPLE__) + m_alignment( 16 ) +#elif defined(_WIN32) + m_alignment( 16 ), + m_commitSize( 0 ), + m_minCommit( 0 ) +#endif + +{ +} + +//------------------------------------- + +CMemoryStack::~CMemoryStack() +{ + if ( m_pBase ) + Term(); +} + +//------------------------------------- + +bool CMemoryStack::Init( unsigned maxSize, unsigned commitSize, unsigned initialCommit, unsigned alignment ) +{ + Assert( !m_pBase ); + +#ifdef _X360 + m_bPhysical = false; +#endif + + m_maxSize = maxSize; + m_alignment = AlignValue( alignment, 4 ); + + Assert( m_alignment == alignment ); + Assert( m_maxSize > 0 ); + +#if defined(_WIN32) + if ( commitSize != 0 ) + { + m_commitSize = commitSize; + } + + unsigned pageSize; + +#ifndef _X360 + SYSTEM_INFO sysInfo; + GetSystemInfo( &sysInfo ); + Assert( !( sysInfo.dwPageSize & (sysInfo.dwPageSize-1)) ); + pageSize = sysInfo.dwPageSize; +#else + pageSize = 64*1024; +#endif + + if ( m_commitSize == 0 ) + { + m_commitSize = pageSize; + } + else + { + m_commitSize = AlignValue( m_commitSize, pageSize ); + } + + m_maxSize = AlignValue( m_maxSize, m_commitSize ); + + Assert( m_maxSize % pageSize == 0 && m_commitSize % pageSize == 0 && m_commitSize <= m_maxSize ); + + m_pBase = (unsigned char *)VirtualAlloc( NULL, m_maxSize, VA_RESERVE_FLAGS, PAGE_NOACCESS ); + Assert( m_pBase ); + m_pCommitLimit = m_pNextAlloc = m_pBase; + + if ( initialCommit ) + { + initialCommit = AlignValue( initialCommit, m_commitSize ); + Assert( initialCommit < m_maxSize ); + if ( !VirtualAlloc( m_pCommitLimit, initialCommit, VA_COMMIT_FLAGS, PAGE_READWRITE ) ) + return false; + m_minCommit = initialCommit; + m_pCommitLimit += initialCommit; + MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() ); + } + +#else + m_pBase = (byte *)MemAlloc_AllocAligned( m_maxSize, alignment ? alignment : 1 ); + m_pNextAlloc = m_pBase; + m_pCommitLimit = m_pBase + m_maxSize; +#endif + + m_pAllocLimit = m_pBase + m_maxSize; + + return ( m_pBase != NULL ); +} + +//------------------------------------- + +#ifdef _X360 +bool CMemoryStack::InitPhysical( unsigned size, unsigned alignment ) +{ + m_bPhysical = true; + + m_maxSize = m_commitSize = size; + m_alignment = AlignValue( alignment, 4 ); + + int flags = PAGE_READWRITE; + if ( size >= 16*1024*1024 ) + { + flags |= MEM_16MB_PAGES; + } + else + { + flags |= MEM_LARGE_PAGES; + } + m_pBase = (unsigned char *)XPhysicalAlloc( m_maxSize, MAXULONG_PTR, 4096, flags ); + Assert( m_pBase ); + m_pNextAlloc = m_pBase; + m_pCommitLimit = m_pBase + m_maxSize; + m_pAllocLimit = m_pBase + m_maxSize; + + MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() ); + return ( m_pBase != NULL ); +} +#endif + +//------------------------------------- + +void CMemoryStack::Term() +{ + FreeAll(); + if ( m_pBase ) + { +#if defined(_WIN32) + VirtualFree( m_pBase, 0, MEM_RELEASE ); +#else + MemAlloc_FreeAligned( m_pBase ); +#endif + m_pBase = NULL; + } +} + +//------------------------------------- + +int CMemoryStack::GetSize() +{ +#ifdef _WIN32 + return m_pCommitLimit - m_pBase; +#else + return m_maxSize; +#endif +} + + +//------------------------------------- + +bool CMemoryStack::CommitTo( byte *pNextAlloc ) RESTRICT +{ +#ifdef _X360 + if ( m_bPhysical ) + { + return NULL; + } +#endif +#if defined(_WIN32) + unsigned char * pNewCommitLimit = AlignValue( pNextAlloc, m_commitSize ); + unsigned commitSize = pNewCommitLimit - m_pCommitLimit; + + if ( GetSize() ) + MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() ); + + if( m_pCommitLimit + commitSize > m_pAllocLimit ) + { + return false; + } + + if ( !VirtualAlloc( m_pCommitLimit, commitSize, VA_COMMIT_FLAGS, PAGE_READWRITE ) ) + { + Assert( 0 ); + return false; + } + m_pCommitLimit = pNewCommitLimit; + + if ( GetSize() ) + MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() ); + return true; +#else + Assert( 0 ); + return false; +#endif +} + +//------------------------------------- + +void CMemoryStack::FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit ) +{ + void *pAllocPoint = m_pBase + mark; + Assert( pAllocPoint >= m_pBase && pAllocPoint <= m_pNextAlloc ); + + if ( pAllocPoint >= m_pBase && pAllocPoint < m_pNextAlloc ) + { + if ( bDecommit ) + { +#if defined(_WIN32) + unsigned char *pDecommitPoint = AlignValue( (unsigned char *)pAllocPoint, m_commitSize ); + + if ( pDecommitPoint < m_pBase + m_minCommit ) + { + pDecommitPoint = m_pBase + m_minCommit; + } + + unsigned decommitSize = m_pCommitLimit - pDecommitPoint; + + if ( decommitSize > 0 ) + { + MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() ); + + VirtualFree( pDecommitPoint, decommitSize, MEM_DECOMMIT ); + m_pCommitLimit = pDecommitPoint; + + if ( mark > 0 ) + { + MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() ); + } + } +#endif + } + m_pNextAlloc = (unsigned char *)pAllocPoint; + } +} + +//------------------------------------- + +void CMemoryStack::FreeAll( bool bDecommit ) +{ + if ( m_pBase && m_pCommitLimit - m_pBase > 0 ) + { + if ( bDecommit ) + { +#if defined(_WIN32) + MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() ); + + VirtualFree( m_pBase, m_pCommitLimit - m_pBase, MEM_DECOMMIT ); + m_pCommitLimit = m_pBase; +#endif + } + m_pNextAlloc = m_pBase; + } +} + +//------------------------------------- + +void CMemoryStack::Access( void **ppRegion, unsigned *pBytes ) +{ + *ppRegion = m_pBase; + *pBytes = ( m_pNextAlloc - m_pBase); +} + +//------------------------------------- + +void CMemoryStack::PrintContents() +{ + Msg( "Total used memory: %d\n", GetUsed() ); + Msg( "Total committed memory: %d\n", GetSize() ); +} + +//----------------------------------------------------------------------------- diff --git a/tier1/newbitbuf.cpp b/tier1/newbitbuf.cpp new file mode 100644 index 00000000..31686a00 --- /dev/null +++ b/tier1/newbitbuf.cpp @@ -0,0 +1,713 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include "bitbuf.h" +#include "coordsize.h" +#include "mathlib/vector.h" +#include "mathlib/mathlib.h" +#include "tier1/strtools.h" +#include "bitvec.h" + +// FIXME: Can't use this until we get multithreaded allocations in tier0 working for tools +// This is used by VVIS and fails to link +// NOTE: This must be the last file included!!! +//#include "tier0/memdbgon.h" + +#ifdef _X360 +// mandatory ... wary of above comment and isolating, tier0 is built as MT though +#include "tier0/memdbgon.h" +#endif + +#include "stdio.h" + +void CBitWrite::StartWriting( void *pData, int nBytes, int iStartBit, int nBits ) +{ + // Make sure it's dword aligned and padded. + Assert( (nBytes % 4) == 0 ); + Assert(((unsigned long)pData & 3) == 0); + Assert( iStartBit == 0 ); + m_pData = (uint32 *) pData; + m_pDataOut = m_pData; + m_nDataBytes = nBytes; + + if ( nBits == -1 ) + { + m_nDataBits = nBytes << 3; + } + else + { + Assert( nBits <= nBytes*8 ); + m_nDataBits = nBits; + } + m_bOverflow = false; + m_nOutBufWord = 0; + m_nOutBitsAvail = 32; + m_pBufferEnd = m_pDataOut + ( nBytes >> 2 ); +} + +const uint32 CBitBuffer::s_nMaskTable[33] = { + 0, + ( 1 << 1 ) - 1, + ( 1 << 2 ) - 1, + ( 1 << 3 ) - 1, + ( 1 << 4 ) - 1, + ( 1 << 5 ) - 1, + ( 1 << 6 ) - 1, + ( 1 << 7 ) - 1, + ( 1 << 8 ) - 1, + ( 1 << 9 ) - 1, + ( 1 << 10 ) - 1, + ( 1 << 11 ) - 1, + ( 1 << 12 ) - 1, + ( 1 << 13 ) - 1, + ( 1 << 14 ) - 1, + ( 1 << 15 ) - 1, + ( 1 << 16 ) - 1, + ( 1 << 17 ) - 1, + ( 1 << 18 ) - 1, + ( 1 << 19 ) - 1, + ( 1 << 20 ) - 1, + ( 1 << 21 ) - 1, + ( 1 << 22 ) - 1, + ( 1 << 23 ) - 1, + ( 1 << 24 ) - 1, + ( 1 << 25 ) - 1, + ( 1 << 26 ) - 1, + ( 1 << 27 ) - 1, + ( 1 << 28 ) - 1, + ( 1 << 29 ) - 1, + ( 1 << 30 ) - 1, + 0x7fffffff, + 0xffffffff, +}; + +bool CBitWrite::WriteString( const char *pStr ) +{ + if(pStr) + { + while( *pStr ) + { + WriteChar( * ( pStr++ ) ); + } + } + WriteChar( 0 ); + return !IsOverflowed(); +} + + +void CBitWrite::WriteLongLong(int64 val) +{ + uint *pLongs = (uint*)&val; + + // Insert the two DWORDS according to network endian + const short endianIndex = 0x0100; + byte *idx = (byte*)&endianIndex; + WriteUBitLong(pLongs[*idx++], sizeof(long) << 3); + WriteUBitLong(pLongs[*idx], sizeof(long) << 3); +} + +bool CBitWrite::WriteBits(const void *pInData, int nBits) +{ + unsigned char *pOut = (unsigned char*)pInData; + int nBitsLeft = nBits; + + // Bounds checking.. + if ( ( GetNumBitsWritten() + nBits) > m_nDataBits ) + { + SetOverflowFlag(); + CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, m_pDebugName ); + return false; + } + + // !! speed!! need fast paths + // write remaining bytes + while ( nBitsLeft >= 8 ) + { + WriteUBitLong( *pOut, 8, false ); + ++pOut; + nBitsLeft -= 8; + } + + // write remaining bits + if ( nBitsLeft ) + { + WriteUBitLong( *pOut, nBitsLeft, false ); + } + + return !IsOverflowed(); +} + +void CBitWrite::WriteBytes( const void *pBuf, int nBytes ) +{ + WriteBits(pBuf, nBytes << 3); +} + +void CBitWrite::WriteBitCoord (const float f) +{ + int signbit = (f <= -COORD_RESOLUTION); + int intval = (int)fabs(f); + int fractval = abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1); + + + // Send the bit flags that indicate whether we have an integer part and/or a fraction part. + WriteOneBit( intval ); + WriteOneBit( fractval ); + + if ( intval || fractval ) + { + // Send the sign bit + WriteOneBit( signbit ); + + // Send the integer if we have one. + if ( intval ) + { + // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] + intval--; + WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS ); + } + + // Send the fraction if we have one + if ( fractval ) + { + WriteUBitLong( (unsigned int)fractval, COORD_FRACTIONAL_BITS ); + } + } +} + +void CBitWrite::WriteBitCoordMP (const float f, bool bIntegral, bool bLowPrecision ) +{ + int signbit = (f <= -( bLowPrecision ? COORD_RESOLUTION_LOWPRECISION : COORD_RESOLUTION )); + int intval = (int)fabs(f); + int fractval = bLowPrecision ? + ( abs((int)(f*COORD_DENOMINATOR_LOWPRECISION)) & (COORD_DENOMINATOR_LOWPRECISION-1) ) : + ( abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1) ); + + bool bInBounds = intval < (1 << COORD_INTEGER_BITS_MP ); + + WriteOneBit( bInBounds ); + + if ( bIntegral ) + { + // Send the sign bit + WriteOneBit( intval ); + if ( intval ) + { + WriteOneBit( signbit ); + // Send the integer if we have one. + // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] + intval--; + if ( bInBounds ) + { + WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS_MP ); + } + else + { + WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS ); + } + } + } + else + { + // Send the bit flags that indicate whether we have an integer part and/or a fraction part. + WriteOneBit( intval ); + // Send the sign bit + WriteOneBit( signbit ); + + // Send the integer if we have one. + if ( intval ) + { + // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] + intval--; + if ( bInBounds ) + { + WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS_MP ); + } + else + { + WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS ); + } + } + WriteUBitLong( (unsigned int)fractval, bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS ); + } +} + +void CBitWrite::SeekToBit( int nBit ) +{ + TempFlush(); + m_pDataOut = m_pData + ( nBit / 32 ); + m_nOutBufWord = *( m_pDataOut ); + m_nOutBitsAvail = 32 - ( nBit & 31 ); +} + + + +void CBitWrite::WriteBitVec3Coord( const Vector& fa ) +{ + int xflag, yflag, zflag; + + xflag = (fa[0] >= COORD_RESOLUTION) || (fa[0] <= -COORD_RESOLUTION); + yflag = (fa[1] >= COORD_RESOLUTION) || (fa[1] <= -COORD_RESOLUTION); + zflag = (fa[2] >= COORD_RESOLUTION) || (fa[2] <= -COORD_RESOLUTION); + + WriteOneBit( xflag ); + WriteOneBit( yflag ); + WriteOneBit( zflag ); + + if ( xflag ) + WriteBitCoord( fa[0] ); + if ( yflag ) + WriteBitCoord( fa[1] ); + if ( zflag ) + WriteBitCoord( fa[2] ); +} + +void CBitWrite::WriteBitNormal( float f ) +{ + int signbit = (f <= -NORMAL_RESOLUTION); + + // NOTE: Since +/-1 are valid values for a normal, I'm going to encode that as all ones + unsigned int fractval = abs( (int)(f*NORMAL_DENOMINATOR) ); + + // clamp.. + if (fractval > NORMAL_DENOMINATOR) + fractval = NORMAL_DENOMINATOR; + + // Send the sign bit + WriteOneBit( signbit ); + + // Send the fractional component + WriteUBitLong( fractval, NORMAL_FRACTIONAL_BITS ); +} + +void CBitWrite::WriteBitVec3Normal( const Vector& fa ) +{ + int xflag, yflag; + + xflag = (fa[0] >= NORMAL_RESOLUTION) || (fa[0] <= -NORMAL_RESOLUTION); + yflag = (fa[1] >= NORMAL_RESOLUTION) || (fa[1] <= -NORMAL_RESOLUTION); + + WriteOneBit( xflag ); + WriteOneBit( yflag ); + + if ( xflag ) + WriteBitNormal( fa[0] ); + if ( yflag ) + WriteBitNormal( fa[1] ); + + // Write z sign bit + int signbit = (fa[2] <= -NORMAL_RESOLUTION); + WriteOneBit( signbit ); +} + +void CBitWrite::WriteBitAngle( float fAngle, int numbits ) +{ + + unsigned int shift = GetBitForBitnum(numbits); + unsigned int mask = shift - 1; + + int d = (int)( (fAngle / 360.0) * shift ); + d &= mask; + + WriteUBitLong((unsigned int)d, numbits); +} + +bool CBitWrite::WriteBitsFromBuffer( bf_read *pIn, int nBits ) +{ +// This could be optimized a little by + while ( nBits > 32 ) + { + WriteUBitLong( pIn->ReadUBitLong( 32 ), 32 ); + nBits -= 32; + } + + WriteUBitLong( pIn->ReadUBitLong( nBits ), nBits ); + return !IsOverflowed() && !pIn->IsOverflowed(); +} + +void CBitWrite::WriteBitAngles( const QAngle& fa ) +{ + // FIXME: + Vector tmp( fa.x, fa.y, fa.z ); + WriteBitVec3Coord( tmp ); +} + +bool CBitRead::Seek( int nPosition ) +{ + bool bSucc = true; + if ( nPosition < 0 || nPosition > m_nDataBits) + { + SetOverflowFlag(); + bSucc = false; + nPosition = m_nDataBits; + } + int nHead = m_nDataBytes & 3; // non-multiple-of-4 bytes at head of buffer. We put the "round off" + // at the head to make reading and detecting the end efficient. + + int nByteOfs = nPosition / 8; + if ( ( m_nDataBytes < 4 ) || ( nHead && ( nByteOfs < nHead ) ) ) + { + // partial first dword + uint8 const *pPartial = ( uint8 const *) m_pData; + if ( m_pData ) + { + m_nInBufWord = *( pPartial++ ); + if ( nHead > 1 ) + m_nInBufWord |= ( *pPartial++ ) << 8; + if ( nHead > 2 ) + m_nInBufWord |= ( *pPartial++ ) << 16; + } + m_pDataIn = ( uint32 const * ) pPartial; + m_nInBufWord >>= ( nPosition & 31 ); + m_nBitsAvail = ( nHead << 3 ) - ( nPosition & 31 ); + } + else + { + int nAdjPosition = nPosition - ( nHead << 3 ); + m_pDataIn = reinterpret_cast ( + reinterpret_cast( m_pData ) + ( ( nAdjPosition / 32 ) << 2 ) + nHead ); + if ( m_pData ) + { + m_nBitsAvail = 32; + GrabNextDWord(); + } + else + { + m_nInBufWord = 0; + m_nBitsAvail = 1; + } + m_nInBufWord >>= ( nAdjPosition & 31 ); + m_nBitsAvail = MIN( m_nBitsAvail, 32 - ( nAdjPosition & 31 ) ); // in case grabnextdword overflowed + } + return bSucc; +} + + +void CBitRead::StartReading( const void *pData, int nBytes, int iStartBit, int nBits ) +{ +// Make sure it's dword aligned and padded. + Assert(((unsigned long)pData & 3) == 0); + m_pData = (uint32 *) pData; + m_pDataIn = m_pData; + m_nDataBytes = nBytes; + + if ( nBits == -1 ) + { + m_nDataBits = nBytes << 3; + } + else + { + Assert( nBits <= nBytes*8 ); + m_nDataBits = nBits; + } + m_bOverflow = false; + m_pBufferEnd = reinterpret_cast ( reinterpret_cast< uint8 const *> (m_pData) + nBytes ); + if ( m_pData ) + Seek( iStartBit ); + +} + +bool CBitRead::ReadString( char *pStr, int maxLen, bool bLine, int *pOutNumChars ) +{ + Assert( maxLen != 0 ); + + bool bTooSmall = false; + int iChar = 0; + while(1) + { + char val = ReadChar(); + if ( val == 0 ) + break; + else if ( bLine && val == '\n' ) + break; + + if ( iChar < (maxLen-1) ) + { + pStr[iChar] = val; + ++iChar; + } + else + { + bTooSmall = true; + } + } + + // Make sure it's null-terminated. + Assert( iChar < maxLen ); + pStr[iChar] = 0; + + if ( pOutNumChars ) + *pOutNumChars = iChar; + + return !IsOverflowed() && !bTooSmall; +} + +char* CBitRead::ReadAndAllocateString( bool *pOverflow ) +{ + char str[2048]; + + int nChars; + bool bOverflow = !ReadString( str, sizeof( str ), false, &nChars ); + if ( pOverflow ) + *pOverflow = bOverflow; + + // Now copy into the output and return it; + char *pRet = new char[ nChars + 1 ]; + for ( int i=0; i <= nChars; i++ ) + pRet[i] = str[i]; + + return pRet; +} + +int64 CBitRead::ReadLongLong( void ) +{ + int64 retval; + uint *pLongs = (uint*)&retval; + + // Read the two DWORDs according to network endian + const short endianIndex = 0x0100; + byte *idx = (byte*)&endianIndex; + pLongs[*idx++] = ReadUBitLong(sizeof(long) << 3); + pLongs[*idx] = ReadUBitLong(sizeof(long) << 3); + return retval; +} + +void CBitRead::ReadBits(void *pOutData, int nBits) +{ + unsigned char *pOut = (unsigned char*)pOutData; + int nBitsLeft = nBits; + + + // align output to dword boundary + while( ((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8 ) + { + *pOut = (unsigned char)ReadUBitLong(8); + ++pOut; + nBitsLeft -= 8; + } + + // X360TBD: Can't read dwords in ReadBits because they'll get swapped + if ( IsPC() ) + { + // read dwords + while ( nBitsLeft >= 32 ) + { + *((unsigned long*)pOut) = ReadUBitLong(32); + pOut += sizeof(unsigned long); + nBitsLeft -= 32; + } + } + + // read remaining bytes + while ( nBitsLeft >= 8 ) + { + *pOut = ReadUBitLong(8); + ++pOut; + nBitsLeft -= 8; + } + + // read remaining bits + if ( nBitsLeft ) + { + *pOut = ReadUBitLong(nBitsLeft); + } + +} + +bool CBitRead::ReadBytes(void *pOut, int nBytes) +{ + ReadBits(pOut, nBytes << 3); + return !IsOverflowed(); +} + +float CBitRead::ReadBitAngle( int numbits ) +{ + float shift = (float)( GetBitForBitnum(numbits) ); + + int i = ReadUBitLong( numbits ); + float fReturn = (float)i * (360.0 / shift); + + return fReturn; +} + +// Basic Coordinate Routines (these contain bit-field size AND fixed point scaling constants) +float CBitRead::ReadBitCoord (void) +{ + int intval=0,fractval=0,signbit=0; + float value = 0.0; + + + // Read the required integer and fraction flags + intval = ReadOneBit(); + fractval = ReadOneBit(); + + // If we got either parse them, otherwise it's a zero. + if ( intval || fractval ) + { + // Read the sign bit + signbit = ReadOneBit(); + + // If there's an integer, read it in + if ( intval ) + { + // Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE] + intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1; + } + + // If there's a fraction, read it in + if ( fractval ) + { + fractval = ReadUBitLong( COORD_FRACTIONAL_BITS ); + } + + // Calculate the correct floating point value + value = intval + ((float)fractval * COORD_RESOLUTION); + + // Fixup the sign if negative. + if ( signbit ) + value = -value; + } + + return value; +} + +float CBitRead::ReadBitCoordMP( bool bIntegral, bool bLowPrecision ) +{ + int intval=0,fractval=0,signbit=0; + float value = 0.0; + + bool bInBounds = ReadOneBit() ? true : false; + + if ( bIntegral ) + { + // Read the required integer and fraction flags + intval = ReadOneBit(); + // If we got either parse them, otherwise it's a zero. + if ( intval ) + { + // Read the sign bit + signbit = ReadOneBit(); + + // If there's an integer, read it in + // Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE] + if ( bInBounds ) + { + value = ReadUBitLong( COORD_INTEGER_BITS_MP ) + 1; + } + else + { + value = ReadUBitLong( COORD_INTEGER_BITS ) + 1; + } + } + } + else + { + // Read the required integer and fraction flags + intval = ReadOneBit(); + + // Read the sign bit + signbit = ReadOneBit(); + + // If we got either parse them, otherwise it's a zero. + if ( intval ) + { + if ( bInBounds ) + { + intval = ReadUBitLong( COORD_INTEGER_BITS_MP ) + 1; + } + else + { + intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1; + } + } + + // If there's a fraction, read it in + fractval = ReadUBitLong( bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS ); + + // Calculate the correct floating point value + value = intval + ((float)fractval * ( bLowPrecision ? COORD_RESOLUTION_LOWPRECISION : COORD_RESOLUTION ) ); + } + + // Fixup the sign if negative. + if ( signbit ) + value = -value; + + return value; +} + +void CBitRead::ReadBitVec3Coord( Vector& fa ) +{ + int xflag, yflag, zflag; + + // This vector must be initialized! Otherwise, If any of the flags aren't set, + // the corresponding component will not be read and will be stack garbage. + fa.Init( 0, 0, 0 ); + + xflag = ReadOneBit(); + yflag = ReadOneBit(); + zflag = ReadOneBit(); + + if ( xflag ) + fa[0] = ReadBitCoord(); + if ( yflag ) + fa[1] = ReadBitCoord(); + if ( zflag ) + fa[2] = ReadBitCoord(); +} + +float CBitRead::ReadBitNormal (void) +{ + // Read the sign bit + int signbit = ReadOneBit(); + + // Read the fractional part + unsigned int fractval = ReadUBitLong( NORMAL_FRACTIONAL_BITS ); + + // Calculate the correct floating point value + float value = (float)fractval * NORMAL_RESOLUTION; + + // Fixup the sign if negative. + if ( signbit ) + value = -value; + + return value; +} + +void CBitRead::ReadBitVec3Normal( Vector& fa ) +{ + int xflag = ReadOneBit(); + int yflag = ReadOneBit(); + + if (xflag) + fa[0] = ReadBitNormal(); + else + fa[0] = 0.0f; + + if (yflag) + fa[1] = ReadBitNormal(); + else + fa[1] = 0.0f; + + // The first two imply the third (but not its sign) + int znegative = ReadOneBit(); + + float fafafbfb = fa[0] * fa[0] + fa[1] * fa[1]; + if (fafafbfb < 1.0f) + fa[2] = sqrt( 1.0f - fafafbfb ); + else + fa[2] = 0.0f; + + if (znegative) + fa[2] = -fa[2]; +} + +void CBitRead::ReadBitAngles( QAngle& fa ) +{ + Vector tmp; + ReadBitVec3Coord( tmp ); + fa.Init( tmp.x, tmp.y, tmp.z ); +} diff --git a/tier1/processor_detect.cpp b/tier1/processor_detect.cpp new file mode 100644 index 00000000..ce1e21fb --- /dev/null +++ b/tier1/processor_detect.cpp @@ -0,0 +1,278 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: win32 dependant ASM code for CPU capability detection +// +// $Workfile: $ +// $NoKeywords: $ +//=============================================================================// + +#if defined _LINUX || defined __APPLE__ + +#include "processor_detect_linux.cpp" + +#elif defined( _X360 ) + +bool CheckMMXTechnology(void) { return false; } +bool CheckSSETechnology(void) { return false; } +bool CheckSSE2Technology(void) { return false; } +bool Check3DNowTechnology(void) { return false; } + +#elif defined( _WIN32 ) && !defined( _X360 ) + +#pragma optimize( "", off ) +#pragma warning( disable: 4800 ) //'int' : forcing value to bool 'true' or 'false' (performance warning) + +// stuff from windows.h +#ifndef EXCEPTION_EXECUTE_HANDLER +#define EXCEPTION_EXECUTE_HANDLER 1 +#endif + +bool CheckMMXTechnology(void) +{ + int retval = true; + unsigned int RegEDX = 0; + +#ifdef CPUID + _asm pushad; +#endif + + __try + { + _asm + { +#ifdef CPUID + xor edx, edx // Clue the compiler that EDX is about to be used. +#endif + mov eax, 1 // set up CPUID to return processor version and features + // 0 = vendor string, 1 = version info, 2 = cache info + CPUID // code bytes = 0fh, 0a2h + mov RegEDX, edx // features returned in edx + } + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + retval = false; + } + + // If CPUID not supported, then certainly no MMX extensions. + if (retval) + { + if (RegEDX & 0x800000) // bit 23 is set for MMX technology + { + __try + { + // try executing the MMX instruction "emms" + _asm EMMS + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + retval = false; + } + } + + else + retval = false; // processor supports CPUID but does not support MMX technology + + // if retval == 0 here, it means the processor has MMX technology but + // floating-point emulation is on; so MMX technology is unavailable + } + +#ifdef CPUID + _asm popad; +#endif + + return retval; +} + +bool CheckSSETechnology(void) +{ + int retval = true; + unsigned int RegEDX = 0; + +#ifdef CPUID + _asm pushad; +#endif + + // Do we have support for the CPUID function? + __try + { + _asm + { +#ifdef CPUID + xor edx, edx // Clue the compiler that EDX is about to be used. +#endif + mov eax, 1 // set up CPUID to return processor version and features + // 0 = vendor string, 1 = version info, 2 = cache info + CPUID // code bytes = 0fh, 0a2h + mov RegEDX, edx // features returned in edx + } + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + retval = false; + } + + // If CPUID not supported, then certainly no SSE extensions. + if (retval) + { + // Do we have support for SSE in this processor? + if ( RegEDX & 0x2000000L ) // bit 25 is set for SSE technology + { + // Make sure that SSE is supported by executing an inline SSE instruction + +// BUGBUG, FIXME - Visual C Version 6.0 does not support SSE inline code YET (No macros from Intel either) +// Fix this if VC7 supports inline SSE instructinons like "xorps" as shown below. +#if 1 + __try + { + _asm + { + // Attempt execution of a SSE instruction to make sure OS supports SSE FPU context switches + xorps xmm0, xmm0 + // This will work on Win2k+ (Including masking SSE FPU exception to "normalized" values) + // This will work on Win98+ (But no "masking" of FPU exceptions provided) + } + } + __except(EXCEPTION_EXECUTE_HANDLER) +#endif + + { + retval = false; + } + } + else + retval = false; + } +#ifdef CPUID + _asm popad; +#endif + + return retval; +} + +bool CheckSSE2Technology(void) +{ + int retval = true; + unsigned int RegEDX = 0; + +#ifdef CPUID + _asm pushad; +#endif + + // Do we have support for the CPUID function? + __try + { + _asm + { +#ifdef CPUID + xor edx, edx // Clue the compiler that EDX is about to be used. +#endif + mov eax, 1 // set up CPUID to return processor version and features + // 0 = vendor string, 1 = version info, 2 = cache info + CPUID // code bytes = 0fh, 0a2h + mov RegEDX, edx // features returned in edx + } + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + retval = false; + } + + // If CPUID not supported, then certainly no SSE extensions. + if (retval) + { + // Do we have support for SSE in this processor? + if ( RegEDX & 0x04000000 ) // bit 26 is set for SSE2 technology + { + // Make sure that SSE is supported by executing an inline SSE instruction + + __try + { + _asm + { + // Attempt execution of a SSE2 instruction to make sure OS supports SSE FPU context switches + xorpd xmm0, xmm0 + } + } + __except(EXCEPTION_EXECUTE_HANDLER) + + { + retval = false; + } + } + else + retval = false; + } +#ifdef CPUID + _asm popad; +#endif + + return retval; +} + +bool Check3DNowTechnology(void) +{ + int retval = true; + unsigned int RegEAX = 0; + +#ifdef CPUID + _asm pushad; +#endif + + // First see if we can execute CPUID at all + __try + { + _asm + { +#ifdef CPUID +// xor edx, edx // Clue the compiler that EDX is about to be used. +#endif + mov eax, 0x80000000 // setup CPUID to return whether AMD >0x80000000 function are supported. + // 0x80000000 = Highest 0x80000000+ function, 0x80000001 = 3DNow support + CPUID // code bytes = 0fh, 0a2h + mov RegEAX, eax // result returned in eax + } + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + retval = false; + } + + // If CPUID not supported, then there is definitely no 3DNow support + if (retval) + { + // Are there any "higher" AMD CPUID functions? + if (RegEAX > 0x80000000L ) + { + __try + { + _asm + { + mov eax, 0x80000001 // setup to test for CPU features + CPUID // code bytes = 0fh, 0a2h + shr edx, 31 // If bit 31 is set, we have 3DNow support! + mov retval, edx // Save the return value for end of function + } + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + retval = false; + } + } + else + { + // processor supports CPUID but does not support AMD CPUID functions + retval = false; + } + } + +#ifdef CPUID + _asm popad; +#endif + + return retval; +} + +#pragma optimize( "", on ) + +#endif // _WIN32 diff --git a/tier1/processor_detect_linux.cpp b/tier1/processor_detect_linux.cpp new file mode 100644 index 00000000..0768bb19 --- /dev/null +++ b/tier1/processor_detect_linux.cpp @@ -0,0 +1,47 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: linux dependant ASM code for CPU capability detection +// +// $Workfile: $ +// $NoKeywords: $ +//=============================================================================// + +#define cpuid(in,a,b,c,d) \ + asm("pushl %%ebx\n\t" "cpuid\n\t" "movl %%ebx,%%esi\n\t" "pop %%ebx": "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (in)); + +bool CheckMMXTechnology(void) +{ + unsigned long eax,ebx,edx,unused; + cpuid(1,eax,ebx,unused,edx); + + return edx & 0x800000; +} + +bool CheckSSETechnology(void) +{ + unsigned long eax,ebx,edx,unused; + cpuid(1,eax,ebx,unused,edx); + + return edx & 0x2000000L; +} + +bool CheckSSE2Technology(void) +{ + unsigned long eax,ebx,edx,unused; + cpuid(1,eax,ebx,unused,edx); + + return edx & 0x04000000; +} + +bool Check3DNowTechnology(void) +{ + unsigned long eax, unused; + cpuid(0x80000000,eax,unused,unused,unused); + + if ( eax > 0x80000000L ) + { + cpuid(0x80000001,unused,unused,unused,eax); + return ( eax & 1<<31 ); + } + return false; +} diff --git a/tier1/rangecheckedvar.cpp b/tier1/rangecheckedvar.cpp new file mode 100644 index 00000000..0ab9c702 --- /dev/null +++ b/tier1/rangecheckedvar.cpp @@ -0,0 +1,41 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "rangecheckedvar.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +bool g_bDoRangeChecks = true; + + +static int g_nDisables = 0; + + +CDisableRangeChecks::CDisableRangeChecks() +{ + if ( !ThreadInMainThread() ) + return; + g_nDisables++; + g_bDoRangeChecks = false; +} + + +CDisableRangeChecks::~CDisableRangeChecks() +{ + if ( !ThreadInMainThread() ) + return; + Assert( g_nDisables > 0 ); + --g_nDisables; + if ( g_nDisables == 0 ) + { + g_bDoRangeChecks = true; + } +} + + + + diff --git a/tier1/stringpool.cpp b/tier1/stringpool.cpp new file mode 100644 index 00000000..c73c9285 --- /dev/null +++ b/tier1/stringpool.cpp @@ -0,0 +1,334 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "convar.h" +#include "tier0/dbg.h" +#include "stringpool.h" +#include "tier1/strtools.h" +#include "generichash.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// Purpose: Comparison function for string sorted associative data structures +//----------------------------------------------------------------------------- + +bool StrLess( const char * const &pszLeft, const char * const &pszRight ) +{ + return ( Q_stricmp( pszLeft, pszRight) < 0 ); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +CStringPool::CStringPool() + : m_Strings( 32, 256, StrLess ) +{ +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +CStringPool::~CStringPool() +{ + FreeAll(); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +unsigned int CStringPool::Count() const +{ + return m_Strings.Count(); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +const char * CStringPool::Find( const char *pszValue ) +{ + unsigned short i = m_Strings.Find(pszValue); + if ( m_Strings.IsValidIndex(i) ) + return m_Strings[i]; + + return NULL; +} + +const char * CStringPool::Allocate( const char *pszValue ) +{ + char *pszNew; + + unsigned short i = m_Strings.Find(pszValue); + bool bNew = (i == m_Strings.InvalidIndex()); + + if ( !bNew ) + return m_Strings[i]; + + pszNew = strdup( pszValue ); + + if ( bNew ) + m_Strings.Insert( pszNew ); + + return pszNew; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void CStringPool::FreeAll() +{ + unsigned short i = m_Strings.FirstInorder(); + while ( i != m_Strings.InvalidIndex() ) + { + free( (void *)m_Strings[i] ); + i = m_Strings.NextInorder(i); + } + m_Strings.RemoveAll(); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + + +CCountedStringPool::CCountedStringPool() +{ + MEM_ALLOC_CREDIT(); + m_HashTable.EnsureCount(HASH_TABLE_SIZE); + + for( int i = 0; i < m_HashTable.Count(); i++ ) + { + m_HashTable[i] = INVALID_ELEMENT; + } + + m_FreeListStart = INVALID_ELEMENT; + m_Elements.AddToTail(); + m_Elements[0].pString = NULL; + m_Elements[0].nReferenceCount = 0; + m_Elements[0].nNextElement = INVALID_ELEMENT; +} + +CCountedStringPool::~CCountedStringPool() +{ + FreeAll(); +} + +void CCountedStringPool::FreeAll() +{ + int i; + + // Reset the hash table: + for( i = 0; i < m_HashTable.Count(); i++ ) + { + m_HashTable[i] = INVALID_ELEMENT; + } + + // Blow away the free list: + m_FreeListStart = INVALID_ELEMENT; + + for( i = 0; i < m_Elements.Count(); i++ ) + { + if( m_Elements[i].pString ) + { + delete [] m_Elements[i].pString; + m_Elements[i].pString = NULL; + m_Elements[i].nReferenceCount = 0; + m_Elements[i].nNextElement = INVALID_ELEMENT; + } + } + + // Remove all but the invalid element: + m_Elements.RemoveAll(); + m_Elements.AddToTail(); + m_Elements[0].pString = NULL; + m_Elements[0].nReferenceCount = 0; + m_Elements[0].nNextElement = INVALID_ELEMENT; +} + + +unsigned short CCountedStringPool::FindStringHandle( const char* pIntrinsic ) +{ + if( pIntrinsic == NULL ) + return INVALID_ELEMENT; + + unsigned short nHashBucketIndex = (HashStringCaseless(pIntrinsic ) %HASH_TABLE_SIZE); + unsigned short nCurrentBucket = m_HashTable[ nHashBucketIndex ]; + + // Does the bucket already exist? + if( nCurrentBucket != INVALID_ELEMENT ) + { + for( ; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement ) + { + if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) ) + { + return nCurrentBucket; + } + } + } + + return 0; + +} + +char* CCountedStringPool::FindString( const char* pIntrinsic ) +{ + if( pIntrinsic == NULL ) + return NULL; + + // Yes, this will be NULL on failure. + return m_Elements[FindStringHandle(pIntrinsic)].pString; +} + +unsigned short CCountedStringPool::ReferenceStringHandle( const char* pIntrinsic ) +{ + if( pIntrinsic == NULL ) + return INVALID_ELEMENT; + + unsigned short nHashBucketIndex = (HashStringCaseless( pIntrinsic ) % HASH_TABLE_SIZE); + unsigned short nCurrentBucket = m_HashTable[ nHashBucketIndex ]; + + // Does the bucket already exist? + if( nCurrentBucket != INVALID_ELEMENT ) + { + for( ; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement ) + { + if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) ) + { + // Anyone who hits 65k references is permanant + if( m_Elements[nCurrentBucket].nReferenceCount < MAX_REFERENCE ) + { + m_Elements[nCurrentBucket].nReferenceCount ++ ; + } + return nCurrentBucket; + } + } + } + + if( m_FreeListStart != INVALID_ELEMENT ) + { + nCurrentBucket = m_FreeListStart; + m_FreeListStart = m_Elements[nCurrentBucket].nNextElement; + } + else + { + nCurrentBucket = m_Elements.AddToTail(); + } + + m_Elements[nCurrentBucket].nReferenceCount = 1; + + // Insert at the beginning of the bucket: + m_Elements[nCurrentBucket].nNextElement = m_HashTable[ nHashBucketIndex ]; + m_HashTable[ nHashBucketIndex ] = nCurrentBucket; + + m_Elements[nCurrentBucket].pString = new char[Q_strlen( pIntrinsic ) + 1]; + Q_strcpy( m_Elements[nCurrentBucket].pString, pIntrinsic ); + + return nCurrentBucket; +} + + +char* CCountedStringPool::ReferenceString( const char* pIntrinsic ) +{ + if(!pIntrinsic) + return NULL; + + return m_Elements[ReferenceStringHandle( pIntrinsic)].pString; +} + +void CCountedStringPool::DereferenceString( const char* pIntrinsic ) +{ + // If we get a NULL pointer, just return + if (!pIntrinsic) + return; + + unsigned short nHashBucketIndex = (HashStringCaseless( pIntrinsic ) % m_HashTable.Count()); + unsigned short nCurrentBucket = m_HashTable[ nHashBucketIndex ]; + + // If there isn't anything in the bucket, just return. + if ( nCurrentBucket == INVALID_ELEMENT ) + return; + + for( unsigned short previous = INVALID_ELEMENT; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement ) + { + if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) ) + { + // Anyone who hits 65k references is permanant + if( m_Elements[nCurrentBucket].nReferenceCount < MAX_REFERENCE ) + { + m_Elements[nCurrentBucket].nReferenceCount --; + } + + if( m_Elements[nCurrentBucket].nReferenceCount == 0 ) + { + if( previous == INVALID_ELEMENT ) + { + m_HashTable[nHashBucketIndex] = m_Elements[nCurrentBucket].nNextElement; + } + else + { + m_Elements[previous].nNextElement = m_Elements[nCurrentBucket].nNextElement; + } + + delete [] m_Elements[nCurrentBucket].pString; + m_Elements[nCurrentBucket].pString = NULL; + m_Elements[nCurrentBucket].nReferenceCount = 0; + + m_Elements[nCurrentBucket].nNextElement = m_FreeListStart; + m_FreeListStart = nCurrentBucket; + break; + + } + } + + previous = nCurrentBucket; + } +} + +char* CCountedStringPool::HandleToString( unsigned short handle ) +{ + return m_Elements[handle].pString; +} + +void CCountedStringPool::SpewStrings() +{ + int i; + for ( i = 0; i < m_Elements.Count(); i++ ) + { + char* string = m_Elements[i].pString; + + Msg("String %d: ref:%d %s", i, m_Elements[i].nReferenceCount, string == NULL? "EMPTY - ok for slot zero only!" : string); + } + + Msg("\n%d total counted strings.", m_Elements.Count()); +} + +#ifdef _DEBUG +CON_COMMAND( test_stringpool, "Tests the class CStringPool" ) +{ + CStringPool pool; + + Assert(pool.Count() == 0); + + pool.Allocate("test"); + Assert(pool.Count() == 1); + + pool.Allocate("test"); + Assert(pool.Count() == 1); + + pool.Allocate("test2"); + Assert(pool.Count() == 2); + + Assert( pool.Find("test2") != NULL ); + Assert( pool.Find("TEST") != NULL ); + Assert( pool.Find("Test2") != NULL ); + Assert( pool.Find("test") != NULL ); + + pool.FreeAll(); + Assert(pool.Count() == 0); + + Msg("Pass."); +} +#endif diff --git a/tier1/strtools.cpp b/tier1/strtools.cpp new file mode 100644 index 00000000..c0f66fd3 --- /dev/null +++ b/tier1/strtools.cpp @@ -0,0 +1,2015 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: String Tools +// +//===========================================================================// + +// These are redefined in the project settings to prevent anyone from using them. +// We in this module are of a higher caste and thus are privileged in their use. +#ifdef strncpy + #undef strncpy +#endif + +#ifdef _snprintf + #undef _snprintf +#endif + +#if defined( sprintf ) + #undef sprintf +#endif + +#if defined( vsprintf ) + #undef vsprintf +#endif + +#ifdef _vsnprintf +#ifdef _WIN32 + #undef _vsnprintf +#endif +#endif + +#ifdef vsnprintf +#ifndef _WIN32 + #undef vsnprintf +#endif +#endif + +#if defined( strcat ) + #undef strcat +#endif + +#ifdef strncat + #undef strncat +#endif + +// NOTE: I have to include stdio + stdarg first so vsnprintf gets compiled in +#include +#include + +#if defined _LINUX || defined __APPLE__ +#include +#include +#include +#define _getcwd getcwd +#elif _WIN32 +#include +#if !defined( _X360 ) +#define WIN32_LEAN_AND_MEAN +#include +#endif +#endif + +#ifdef _WIN32 +#ifndef CP_UTF8 +#define CP_UTF8 65001 +#endif +#endif +#include "tier0/dbg.h" +#include "tier1/strtools.h" +#include +#include +#include "tier0/basetypes.h" +#include "tier1/utldict.h" +#if defined( _X360 ) +#include "xbox/xbox_win32stubs.h" +#endif +#include "tier0/memdbgon.h" + +void _V_memset (const char* file, int line, void *dest, int fill, int count) +{ + Assert( count >= 0 ); + AssertValidWritePtr( dest, count ); + + memset(dest,fill,count); +} + +void _V_memcpy (const char* file, int line, void *dest, const void *src, int count) +{ + Assert( count >= 0 ); + AssertValidReadPtr( src, count ); + AssertValidWritePtr( dest, count ); + + memcpy( dest, src, count ); +} + +void _V_memmove(const char* file, int line, void *dest, const void *src, int count) +{ + Assert( count >= 0 ); + AssertValidReadPtr( src, count ); + AssertValidWritePtr( dest, count ); + + memmove( dest, src, count ); +} + +int _V_memcmp (const char* file, int line, const void *m1, const void *m2, int count) +{ + Assert( count >= 0 ); + AssertValidReadPtr( m1, count ); + AssertValidReadPtr( m2, count ); + + return memcmp( m1, m2, count ); +} + +int _V_strlen(const char* file, int line, const char *str) +{ + AssertValidStringPtr(str); + return strlen( str ); +} + +void _V_strcpy (const char* file, int line, char *dest, const char *src) +{ + AssertValidWritePtr(dest); + AssertValidStringPtr(src); + + strcpy( dest, src ); +} + +int _V_wcslen(const char* file, int line, const wchar_t *pwch) +{ + return wcslen( pwch ); +} + +char *_V_strrchr(const char* file, int line, const char *s, char c) +{ + AssertValidStringPtr( s ); + int len = V_strlen(s); + s += len; + while (len--) + if (*--s == c) return (char *)s; + return 0; +} + +int _V_strcmp (const char* file, int line, const char *s1, const char *s2) +{ + AssertValidStringPtr( s1 ); + AssertValidStringPtr( s2 ); + + return strcmp( s1, s2 ); +} + +int _V_wcscmp (const char* file, int line, const wchar_t *s1, const wchar_t *s2) +{ + while (1) + { + if (*s1 != *s2) + return -1; // strings not equal + if (!*s1) + return 0; // strings are equal + s1++; + s2++; + } + + return -1; +} + + + +int _V_stricmp(const char* file, int line, const char *s1, const char *s2 ) +{ + AssertValidStringPtr( s1 ); + AssertValidStringPtr( s2 ); + + return stricmp( s1, s2 ); +} + + +char *_V_strstr(const char* file, int line, const char *s1, const char *search ) +{ + AssertValidStringPtr( s1 ); + AssertValidStringPtr( search ); + +#if defined( _X360 ) + return (char *)strstr( (char *)s1, search ); +#else + return (char *)strstr( s1, search ); +#endif +} + +char *_V_strupr (const char* file, int line, char *start) +{ + AssertValidStringPtr( start ); + return strupr( start ); +} + + +char *_V_strlower (const char* file, int line, char *start) +{ + AssertValidStringPtr( start ); + return strlwr(start); +} + +int V_strncmp (const char *s1, const char *s2, int count) +{ + Assert( count >= 0 ); + AssertValidStringPtr( s1, count ); + AssertValidStringPtr( s2, count ); + + while ( count-- > 0 ) + { + if ( *s1 != *s2 ) + return *s1 < *s2 ? -1 : 1; // string different + if ( *s1 == '\0' ) + return 0; // null terminator hit - strings the same + s1++; + s2++; + } + + return 0; // count characters compared the same +} + +char *V_strnlwr(char *s, size_t count) +{ + Assert( count >= 0 ); + AssertValidStringPtr( s, count ); + + char* pRet = s; + if ( !s ) + return s; + + while ( --count >= 0 ) + { + if ( !*s ) + break; + + *s = tolower( *s ); + ++s; + } + + if ( count > 0 ) + { + s[count-1] = 0; + } + + return pRet; +} + + +int V_strncasecmp (const char *s1, const char *s2, int n) +{ + Assert( n >= 0 ); + AssertValidStringPtr( s1 ); + AssertValidStringPtr( s2 ); + + while ( n-- > 0 ) + { + int c1 = *s1++; + int c2 = *s2++; + + if (c1 != c2) + { + if (c1 >= 'a' && c1 <= 'z') + c1 -= ('a' - 'A'); + if (c2 >= 'a' && c2 <= 'z') + c2 -= ('a' - 'A'); + if (c1 != c2) + return c1 < c2 ? -1 : 1; + } + if ( c1 == '\0' ) + return 0; // null terminator hit - strings the same + } + + return 0; // n characters compared the same +} + +int V_strcasecmp( const char *s1, const char *s2 ) +{ + AssertValidStringPtr( s1 ); + AssertValidStringPtr( s2 ); + + return stricmp( s1, s2 ); +} + +int V_strnicmp (const char *s1, const char *s2, int n) +{ + Assert( n >= 0 ); + AssertValidStringPtr(s1); + AssertValidStringPtr(s2); + + return V_strncasecmp( s1, s2, n ); +} + + +const char *StringAfterPrefix( const char *str, const char *prefix ) +{ + AssertValidStringPtr( str ); + AssertValidStringPtr( prefix ); + do + { + if ( !*prefix ) + return str; + } + while ( tolower( *str++ ) == tolower( *prefix++ ) ); + return NULL; +} + +const char *StringAfterPrefixCaseSensitive( const char *str, const char *prefix ) +{ + AssertValidStringPtr( str ); + AssertValidStringPtr( prefix ); + do + { + if ( !*prefix ) + return str; + } + while ( *str++ == *prefix++ ); + return NULL; +} + + +int V_atoi (const char *str) +{ + AssertValidStringPtr( str ); + + int val; + int sign; + int c; + + Assert( str ); + if (*str == '-') + { + sign = -1; + str++; + } + else + sign = 1; + + val = 0; + +// +// check for hex +// + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') ) + { + str += 2; + while (1) + { + c = *str++; + if (c >= '0' && c <= '9') + val = (val<<4) + c - '0'; + else if (c >= 'a' && c <= 'f') + val = (val<<4) + c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + val = (val<<4) + c - 'A' + 10; + else + return val*sign; + } + } + +// +// check for character +// + if (str[0] == '\'') + { + return sign * str[1]; + } + +// +// assume decimal +// + while (1) + { + c = *str++; + if (c <'0' || c > '9') + return val*sign; + val = val*10 + c - '0'; + } + + return 0; +} + + +float V_atof (const char *str) +{ + AssertValidStringPtr( str ); + double val; + int sign; + int c; + int decimal, total; + + if (*str == '-') + { + sign = -1; + str++; + } + else + sign = 1; + + val = 0; + +// +// check for hex +// + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') ) + { + str += 2; + while (1) + { + c = *str++; + if (c >= '0' && c <= '9') + val = (val*16) + c - '0'; + else if (c >= 'a' && c <= 'f') + val = (val*16) + c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + val = (val*16) + c - 'A' + 10; + else + return val*sign; + } + } + +// +// check for character +// + if (str[0] == '\'') + { + return sign * str[1]; + } + +// +// assume decimal +// + decimal = -1; + total = 0; + while (1) + { + c = *str++; + if (c == '.') + { + decimal = total; + continue; + } + if (c <'0' || c > '9') + break; + val = val*10 + c - '0'; + total++; + } + + if (decimal == -1) + return val*sign; + while (total > decimal) + { + val /= 10; + total--; + } + + return val*sign; +} + +//----------------------------------------------------------------------------- +// Normalizes a float string in place. +// +// (removes leading zeros, trailing zeros after the decimal point, and the decimal point itself where possible) +//----------------------------------------------------------------------------- +void V_normalizeFloatString( char* pFloat ) +{ + // If we have a decimal point, remove trailing zeroes: + if( strchr( pFloat,'.' ) ) + { + int len = V_strlen(pFloat); + + while( len > 1 && pFloat[len - 1] == '0' ) + { + pFloat[len - 1] = '\0'; + len--; + } + + if( len > 1 && pFloat[ len - 1 ] == '.' ) + { + pFloat[len - 1] = '\0'; + len--; + } + } + + // TODO: Strip leading zeros + +} + + +//----------------------------------------------------------------------------- +// Finds a string in another string with a case insensitive test +//----------------------------------------------------------------------------- +char const* V_stristr( char const* pStr, char const* pSearch ) +{ + AssertValidStringPtr(pStr); + AssertValidStringPtr(pSearch); + + if (!pStr || !pSearch) + return 0; + + char const* pLetter = pStr; + + // Check the entire string + while (*pLetter != 0) + { + // Skip over non-matches + if (tolower((unsigned char)*pLetter) == tolower((unsigned char)*pSearch)) + { + // Check for match + char const* pMatch = pLetter + 1; + char const* pTest = pSearch + 1; + while (*pTest != 0) + { + // We've run off the end; don't bother. + if (*pMatch == 0) + return 0; + + if (tolower((unsigned char)*pMatch) != tolower((unsigned char)*pTest)) + break; + + ++pMatch; + ++pTest; + } + + // Found a match! + if (*pTest == 0) + return pLetter; + } + + ++pLetter; + } + + return 0; +} + +char* V_stristr( char* pStr, char const* pSearch ) +{ + AssertValidStringPtr( pStr ); + AssertValidStringPtr( pSearch ); + + return (char*)V_stristr( (char const*)pStr, pSearch ); +} + +//----------------------------------------------------------------------------- +// Finds a string in another string with a case insensitive test w/ length validation +//----------------------------------------------------------------------------- +char const* V_strnistr( char const* pStr, char const* pSearch, int n ) +{ + AssertValidStringPtr(pStr); + AssertValidStringPtr(pSearch); + + if (!pStr || !pSearch) + return 0; + + char const* pLetter = pStr; + + // Check the entire string + while (*pLetter != 0) + { + if ( n <= 0 ) + return 0; + + // Skip over non-matches + if (tolower(*pLetter) == tolower(*pSearch)) + { + int n1 = n - 1; + + // Check for match + char const* pMatch = pLetter + 1; + char const* pTest = pSearch + 1; + while (*pTest != 0) + { + if ( n1 <= 0 ) + return 0; + + // We've run off the end; don't bother. + if (*pMatch == 0) + return 0; + + if (tolower(*pMatch) != tolower(*pTest)) + break; + + ++pMatch; + ++pTest; + --n1; + } + + // Found a match! + if (*pTest == 0) + return pLetter; + } + + ++pLetter; + --n; + } + + return 0; +} + +const char* V_strnchr( const char* pStr, char c, int n ) +{ + char const* pLetter = pStr; + char const* pLast = pStr + n; + + // Check the entire string + while ( (pLetter < pLast) && (*pLetter != 0) ) + { + if (*pLetter == c) + return pLetter; + ++pLetter; + } + return NULL; +} + +void V_strncpy( char *pDest, char const *pSrc, int maxLen ) +{ + Assert( maxLen >= 0 ); + AssertValidWritePtr( pDest, maxLen ); + AssertValidStringPtr( pSrc ); + + strncpy( pDest, pSrc, maxLen ); + if ( maxLen > 0 ) + { + pDest[maxLen-1] = 0; + } +} + +void V_wcsncpy( wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes ) +{ + Assert( maxLenInBytes >= 0 ); + AssertValidWritePtr( pDest, maxLenInBytes ); + AssertValidReadPtr( pSrc ); + + int maxLen = maxLenInBytes / sizeof(wchar_t); + + wcsncpy( pDest, pSrc, maxLen ); + if( maxLen ) + { + pDest[maxLen-1] = 0; + } +} + + + +int V_snwprintf( wchar_t *pDest, int maxLen, const wchar_t *pFormat, ... ) +{ + Assert( maxLen >= 0 ); + AssertValidWritePtr( pDest, maxLen ); + AssertValidReadPtr( pFormat ); + + va_list marker; + + va_start( marker, pFormat ); +#ifdef _WIN32 + int len = _snwprintf( pDest, maxLen, pFormat, marker ); +#elif defined _LINUX || defined __APPLE__ + int len = swprintf( pDest, maxLen, pFormat, marker ); +#else +#error "define vsnwprintf type." +#endif + va_end( marker ); + + // Len < 0 represents an overflow + if( len < 0 ) + { + len = maxLen; + pDest[maxLen-1] = 0; + } + + return len; +} + + +int V_snprintf( char *pDest, int maxLen, char const *pFormat, ... ) +{ + Assert( maxLen >= 0 ); + AssertValidWritePtr( pDest, maxLen ); + AssertValidStringPtr( pFormat ); + + va_list marker; + + va_start( marker, pFormat ); +#ifdef _WIN32 + int len = _vsnprintf( pDest, maxLen, pFormat, marker ); +#elif defined _LINUX || defined __APPLE__ + int len = vsnprintf( pDest, maxLen, pFormat, marker ); +#else + #error "define vsnprintf type." +#endif + va_end( marker ); + + // Len < 0 represents an overflow + if( len < 0 ) + { + len = maxLen; + pDest[maxLen-1] = 0; + } + + return len; +} + + +int V_vsnprintf( char *pDest, int maxLen, char const *pFormat, va_list params ) +{ + Assert( maxLen > 0 ); + AssertValidWritePtr( pDest, maxLen ); + AssertValidStringPtr( pFormat ); + + int len = _vsnprintf( pDest, maxLen, pFormat, params ); + + if( len < 0 ) + { + len = maxLen; + pDest[maxLen-1] = 0; + } + + return len; +} + + + +//----------------------------------------------------------------------------- +// Purpose: If COPY_ALL_CHARACTERS == max_chars_to_copy then we try to add the whole pSrc to the end of pDest, otherwise +// we copy only as many characters as are specified in max_chars_to_copy (or the # of characters in pSrc if thats's less). +// Input : *pDest - destination buffer +// *pSrc - string to append +// destBufferSize - sizeof the buffer pointed to by pDest +// max_chars_to_copy - COPY_ALL_CHARACTERS in pSrc or max # to copy +// Output : char * the copied buffer +//----------------------------------------------------------------------------- +char *V_strncat(char *pDest, const char *pSrc, size_t destBufferSize, int max_chars_to_copy ) +{ + size_t charstocopy = (size_t)0; + + Assert( destBufferSize >= 0 ); + AssertValidStringPtr( pDest); + AssertValidStringPtr( pSrc ); + + size_t len = strlen(pDest); + size_t srclen = strlen( pSrc ); + if ( max_chars_to_copy <= COPY_ALL_CHARACTERS ) + { + charstocopy = srclen; + } + else + { + charstocopy = (size_t)MIN( max_chars_to_copy, (int)srclen ); + } + + if ( len + charstocopy >= destBufferSize ) + { + charstocopy = destBufferSize - len - 1; + } + + if ( !charstocopy ) + { + return pDest; + } + + char *pOut = strncat( pDest, pSrc, charstocopy ); + pOut[destBufferSize-1] = 0; + return pOut; +} + + + +//----------------------------------------------------------------------------- +// Purpose: Converts value into x.xx MB/ x.xx KB, x.xx bytes format, including commas +// Input : value - +// 2 - +// false - +// Output : char +//----------------------------------------------------------------------------- +#define NUM_PRETIFYMEM_BUFFERS 8 +char *V_pretifymem( float value, int digitsafterdecimal /*= 2*/, bool usebinaryonek /*= false*/ ) +{ + static char output[ NUM_PRETIFYMEM_BUFFERS ][ 32 ]; + static int current; + + float onekb = usebinaryonek ? 1024.0f : 1000.0f; + float onemb = onekb * onekb; + + char *out = output[ current ]; + current = ( current + 1 ) & ( NUM_PRETIFYMEM_BUFFERS -1 ); + + char suffix[ 8 ]; + + // First figure out which bin to use + if ( value > onemb ) + { + value /= onemb; + V_snprintf( suffix, sizeof( suffix ), " MB" ); + } + else if ( value > onekb ) + { + value /= onekb; + V_snprintf( suffix, sizeof( suffix ), " KB" ); + } + else + { + V_snprintf( suffix, sizeof( suffix ), " bytes" ); + } + + char val[ 32 ]; + + // Clamp to >= 0 + digitsafterdecimal = MAX( digitsafterdecimal, 0 ); + + // If it's basically integral, don't do any decimals + if ( FloatMakePositive( value - (int)value ) < 0.00001 ) + { + V_snprintf( val, sizeof( val ), "%i%s", (int)value, suffix ); + } + else + { + char fmt[ 32 ]; + + // Otherwise, create a format string for the decimals + V_snprintf( fmt, sizeof( fmt ), "%%.%if%s", digitsafterdecimal, suffix ); + V_snprintf( val, sizeof( val ), fmt, value ); + } + + // Copy from in to out + char *i = val; + char *o = out; + + // Search for decimal or if it was integral, find the space after the raw number + char *dot = strstr( i, "." ); + if ( !dot ) + { + dot = strstr( i, " " ); + } + + // Compute position of dot + int pos = dot - i; + // Don't put a comma if it's <= 3 long + pos -= 3; + + while ( *i ) + { + // If pos is still valid then insert a comma every third digit, except if we would be + // putting one in the first spot + if ( pos >= 0 && !( pos % 3 ) ) + { + // Never in first spot + if ( o != out ) + { + *o++ = ','; + } + } + + // Count down comma position + pos--; + + // Copy rest of data as normal + *o++ = *i++; + } + + // Terminate + *o = 0; + + return out; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns a string representation of an integer with commas +// separating the 1000s (ie, 37,426,421) +// Input : value - Value to convert +// Output : Pointer to a static buffer containing the output +//----------------------------------------------------------------------------- +#define NUM_PRETIFYNUM_BUFFERS 8 +char *V_pretifynum( int64 value ) +{ + static char output[ NUM_PRETIFYMEM_BUFFERS ][ 32 ]; + static int current; + + char *out = output[ current ]; + current = ( current + 1 ) & ( NUM_PRETIFYMEM_BUFFERS -1 ); + + *out = 0; + + // Render the leading -, if necessary + if ( value < 0 ) + { + char *pchRender = out + V_strlen( out ); + V_snprintf( pchRender, 32, "-" ); + value = -value; + } + + // Render quadrillions + if ( value >= 1000000000000LL ) + { + char *pchRender = out + V_strlen( out ); + V_snprintf( pchRender, 32, "%d,", value / 1000000000000LL ); + } + + // Render trillions + if ( value >= 1000000000000LL ) + { + char *pchRender = out + V_strlen( out ); + V_snprintf( pchRender, 32, "%d,", value / 1000000000000LL ); + } + + // Render billions + if ( value >= 1000000000 ) + { + char *pchRender = out + V_strlen( out ); + V_snprintf( pchRender, 32, "%d,", value / 1000000000 ); + } + + // Render millions + if ( value >= 1000000 ) + { + char *pchRender = out + V_strlen( out ); + if ( value >= 1000000000 ) + V_snprintf( pchRender, 32, "%03d,", ( value / 1000000 ) % 1000 ); + else + V_snprintf( pchRender, 32, "%d,", ( value / 1000000 ) % 1000 ); + } + + // Render thousands + if ( value >= 1000 ) + { + char *pchRender = out + V_strlen( out ); + if ( value >= 1000000 ) + V_snprintf( pchRender, 32, "%03d,", ( value / 1000 ) % 1000 ); + else + V_snprintf( pchRender, 32, "%d,", ( value / 1000 ) % 1000 ); + } + + // Render units + char *pchRender = out + V_strlen( out ); + if ( value > 1000 ) + V_snprintf( pchRender, 32, "%03d", value % 1000 ); + else + V_snprintf( pchRender, 32, "%d", value % 1000 ); + + return out; +} + + +//----------------------------------------------------------------------------- +// Purpose: Converts a UTF8 string into a unicode string +//----------------------------------------------------------------------------- +int V_UTF8ToUnicode( const char *pUTF8, wchar_t *pwchDest, int cubDestSizeInBytes ) +{ + AssertValidStringPtr(pUTF8); + AssertValidWritePtr(pwchDest); + + pwchDest[0] = 0; +#ifdef _WIN32 + int cchResult = MultiByteToWideChar( CP_UTF8, 0, pUTF8, -1, pwchDest, cubDestSizeInBytes / sizeof(wchar_t) ); +#elif defined _LINUX || defined __APPLE__ + int cchResult = mbstowcs( pwchDest, pUTF8, cubDestSizeInBytes / sizeof(wchar_t) ); +#endif + pwchDest[(cubDestSizeInBytes / sizeof(wchar_t)) - 1] = 0; + return cchResult; +} + +//----------------------------------------------------------------------------- +// Purpose: Converts a unicode string into a UTF8 (standard) string +//----------------------------------------------------------------------------- +int V_UnicodeToUTF8( const wchar_t *pUnicode, char *pUTF8, int cubDestSizeInBytes ) +{ + AssertValidStringPtr(pUTF8, cubDestSizeInBytes); + AssertValidReadPtr(pUnicode); + + pUTF8[0] = 0; +#ifdef _WIN32 + int cchResult = WideCharToMultiByte( CP_UTF8, 0, pUnicode, -1, pUTF8, cubDestSizeInBytes, NULL, NULL ); +#elif defined _LINUX || defined __APPLE__ + int cchResult = wcstombs( pUTF8, pUnicode, cubDestSizeInBytes ); +#endif + pUTF8[cubDestSizeInBytes - 1] = 0; + return cchResult; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns the 4 bit nibble for a hex character +// Input : c - +// Output : unsigned char +//----------------------------------------------------------------------------- +static unsigned char V_nibble( char c ) +{ + if ( ( c >= '0' ) && + ( c <= '9' ) ) + { + return (unsigned char)(c - '0'); + } + + if ( ( c >= 'A' ) && + ( c <= 'F' ) ) + { + return (unsigned char)(c - 'A' + 0x0a); + } + + if ( ( c >= 'a' ) && + ( c <= 'f' ) ) + { + return (unsigned char)(c - 'a' + 0x0a); + } + + return '0'; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *in - +// numchars - +// *out - +// maxoutputbytes - +//----------------------------------------------------------------------------- +void V_hextobinary( char const *in, int numchars, byte *out, int maxoutputbytes ) +{ + int len = V_strlen( in ); + numchars = MIN( len, numchars ); + // Make sure it's even + numchars = ( numchars ) & ~0x1; + + // Must be an even # of input characters (two chars per output byte) + Assert( numchars >= 2 ); + + memset( out, 0x00, maxoutputbytes ); + + byte *p; + int i; + + p = out; + for ( i = 0; + ( i < numchars ) && ( ( p - out ) < maxoutputbytes ); + i+=2, p++ ) + { + *p = ( V_nibble( in[i] ) << 4 ) | V_nibble( in[i+1] ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *in - +// inputbytes - +// *out - +// outsize - +//----------------------------------------------------------------------------- +void V_binarytohex( const byte *in, int inputbytes, char *out, int outsize ) +{ + Assert( outsize >= 1 ); + char doublet[10]; + int i; + + out[0]=0; + + for ( i = 0; i < inputbytes; i++ ) + { + unsigned char c = in[i]; + V_snprintf( doublet, sizeof( doublet ), "%02x", c ); + V_strncat( out, doublet, outsize, COPY_ALL_CHARACTERS ); + } +} + +#if defined( _WIN32 ) || defined( WIN32 ) +#define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/') +#else //_WIN32 +#define PATHSEPARATOR(c) ((c) == '/') +#endif //_WIN32 + + +//----------------------------------------------------------------------------- +// Purpose: Extracts the base name of a file (no path, no extension, assumes '/' or '\' as path separator) +// Input : *in - +// *out - +// maxlen - +//----------------------------------------------------------------------------- +void V_FileBase( const char *in, char *out, int maxlen ) +{ + Assert( maxlen >= 1 ); + Assert( in ); + Assert( out ); + + if ( !in || !in[ 0 ] ) + { + *out = 0; + return; + } + + int len, start, end; + + len = V_strlen( in ); + + // scan backward for '.' + end = len - 1; + while ( end&& in[end] != '.' && !PATHSEPARATOR( in[end] ) ) + { + end--; + } + + if ( in[end] != '.' ) // no '.', copy to end + { + end = len-1; + } + else + { + end--; // Found ',', copy to left of '.' + } + + // Scan backward for '/' + start = len-1; + while ( start >= 0 && !PATHSEPARATOR( in[start] ) ) + { + start--; + } + + if ( start < 0 || !PATHSEPARATOR( in[start] ) ) + { + start = 0; + } + else + { + start++; + } + + // Length of new sting + len = end - start + 1; + + int maxcopy = MIN( len + 1, maxlen ); + + // Copy partial string + V_strncpy( out, &in[start], maxcopy ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *ppath - +//----------------------------------------------------------------------------- +void V_StripTrailingSlash( char *ppath ) +{ + Assert( ppath ); + + int len = V_strlen( ppath ); + if ( len > 0 ) + { + if ( PATHSEPARATOR( ppath[ len - 1 ] ) ) + { + ppath[ len - 1 ] = 0; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *in - +// *out - +// outSize - +//----------------------------------------------------------------------------- +void V_StripExtension( const char *in, char *out, int outSize ) +{ + // Find the last dot. If it's followed by a dot or a slash, then it's part of a + // directory specifier like ../../somedir/./blah. + + // scan backward for '.' + int end = V_strlen( in ) - 1; + while ( end > 0 && in[end] != '.' && !PATHSEPARATOR( in[end] ) ) + { + --end; + } + + if (end > 0 && !PATHSEPARATOR( in[end] ) && end < outSize) + { + int nChars = MIN( end, outSize-1 ); + if ( out != in ) + { + memcpy( out, in, nChars ); + } + out[nChars] = 0; + } + else + { + // nothing found + if ( out != in ) + { + V_strncpy( out, in, outSize ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *path - +// *extension - +// pathStringLength - +//----------------------------------------------------------------------------- +void V_DefaultExtension( char *path, const char *extension, int pathStringLength ) +{ + Assert( path ); + Assert( pathStringLength >= 1 ); + Assert( extension ); + Assert( extension[0] == '.' ); + + char *src; + + // if path doesn't have a .EXT, append extension + // (extension should include the .) + src = path + V_strlen(path) - 1; + + while ( !PATHSEPARATOR( *src ) && ( src > path ) ) + { + if (*src == '.') + { + // it has an extension + return; + } + src--; + } + + // Concatenate the desired extension + V_strncat( path, extension, pathStringLength, COPY_ALL_CHARACTERS ); +} + +//----------------------------------------------------------------------------- +// Purpose: Force extension... +// Input : *path - +// *extension - +// pathStringLength - +//----------------------------------------------------------------------------- +void V_SetExtension( char *path, const char *extension, int pathStringLength ) +{ + V_StripExtension( path, path, pathStringLength ); + V_DefaultExtension( path, extension, pathStringLength ); +} + +//----------------------------------------------------------------------------- +// Purpose: Remove final filename from string +// Input : *path - +// Output : void V_StripFilename +//----------------------------------------------------------------------------- +void V_StripFilename (char *path) +{ + int length; + + length = V_strlen( path )-1; + if ( length <= 0 ) + return; + + while ( length > 0 && + !PATHSEPARATOR( path[length] ) ) + { + length--; + } + + path[ length ] = 0; +} + +#ifdef _WIN32 +#define CORRECT_PATH_SEPARATOR '\\' +#define INCORRECT_PATH_SEPARATOR '/' +#elif defined _LINUX || defined __APPLE__ +#define CORRECT_PATH_SEPARATOR '/' +#define INCORRECT_PATH_SEPARATOR '\\' +#endif + +//----------------------------------------------------------------------------- +// Purpose: Changes all '/' or '\' characters into separator +// Input : *pname - +// separator - +//----------------------------------------------------------------------------- +void V_FixSlashes( char *pname, char separator /* = CORRECT_PATH_SEPARATOR */ ) +{ + while ( *pname ) + { + if ( *pname == INCORRECT_PATH_SEPARATOR || *pname == CORRECT_PATH_SEPARATOR ) + { + *pname = separator; + } + pname++; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: This function fixes cases of filenames like materials\\blah.vmt or somepath\otherpath\\ and removes the extra double slash. +//----------------------------------------------------------------------------- +void V_FixDoubleSlashes( char *pStr ) +{ + int len = V_strlen( pStr ); + + for ( int i=1; i < len-1; i++ ) + { + if ( (pStr[i] == '/' || pStr[i] == '\\') && (pStr[i+1] == '/' || pStr[i+1] == '\\') ) + { + // This means there's a double slash somewhere past the start of the filename. That + // can happen in Hammer if they use a material in the root directory. You'll get a filename + // that looks like 'materials\\blah.vmt' + V_memmove( &pStr[i], &pStr[i+1], len - i ); + --len; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Strip off the last directory from dirName +// Input : *dirName - +// maxlen - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool V_StripLastDir( char *dirName, int maxlen ) +{ + if( dirName[0] == 0 || + !V_stricmp( dirName, "./" ) || + !V_stricmp( dirName, ".\\" ) ) + return false; + + int len = V_strlen( dirName ); + + Assert( len < maxlen ); + + // skip trailing slash + if ( PATHSEPARATOR( dirName[len-1] ) ) + { + len--; + } + + while ( len > 0 ) + { + if ( PATHSEPARATOR( dirName[len-1] ) ) + { + dirName[len] = 0; + V_FixSlashes( dirName, CORRECT_PATH_SEPARATOR ); + return true; + } + len--; + } + + // Allow it to return an empty string and true. This can happen if something like "tf2/" is passed in. + // The correct behavior is to strip off the last directory ("tf2") and return true. + if( len == 0 ) + { + V_snprintf( dirName, maxlen, ".%c", CORRECT_PATH_SEPARATOR ); + return true; + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns a pointer to the beginning of the unqualified file name +// (no path information) +// Input: in - file name (may be unqualified, relative or absolute path) +// Output: pointer to unqualified file name +//----------------------------------------------------------------------------- +const char * V_UnqualifiedFileName( const char * in ) +{ + // back up until the character after the first path separator we find, + // or the beginning of the string + const char * out = in + strlen( in ) - 1; + while ( ( out > in ) && ( !PATHSEPARATOR( *( out-1 ) ) ) ) + out--; + return out; +} + + +//----------------------------------------------------------------------------- +// Purpose: Composes a path and filename together, inserting a path separator +// if need be +// Input: path - path to use +// filename - filename to use +// dest - buffer to compose result in +// destSize - size of destination buffer +//----------------------------------------------------------------------------- +void V_ComposeFileName( const char *path, const char *filename, char *dest, int destSize ) +{ + V_strncpy( dest, path, destSize ); + V_AppendSlash( dest, destSize ); + V_strncat( dest, filename, destSize, COPY_ALL_CHARACTERS ); + V_FixSlashes( dest ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *path - +// *dest - +// destSize - +// Output : void V_ExtractFilePath +//----------------------------------------------------------------------------- +bool V_ExtractFilePath (const char *path, char *dest, int destSize ) +{ + Assert( destSize >= 1 ); + if ( destSize < 1 ) + { + return false; + } + + // Last char + int len = V_strlen(path); + const char *src = path + (len ? len-1 : 0); + + // back up until a \ or the start + while ( src != path && !PATHSEPARATOR( *(src-1) ) ) + { + src--; + } + + int copysize = MIN( src - path, destSize - 1 ); + memcpy( dest, path, copysize ); + dest[copysize] = 0; + + return copysize != 0 ? true : false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *path - +// *dest - +// destSize - +// Output : void V_ExtractFileExtension +//----------------------------------------------------------------------------- +void V_ExtractFileExtension( const char *path, char *dest, int destSize ) +{ + *dest = '\0'; + const char * extension = V_GetFileExtension( path ); + if ( NULL != extension ) + V_strncpy( dest, extension, destSize ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns a pointer to the file extension within a file name string +// Input: in - file name +// Output: pointer to beginning of extension (after the "."), or NULL +// if there is no extension +//----------------------------------------------------------------------------- +const char * V_GetFileExtension( const char * path ) +{ + const char *src; + + src = path + strlen(path) - 1; + +// +// back up until a . or the start +// + while (src != path && *(src-1) != '.' ) + src--; + + // check to see if the '.' is part of a pathname + if (src == path || PATHSEPARATOR( *src ) ) + { + return NULL; // no extension + } + + return src; +} + +bool V_RemoveDotSlashes( char *pFilename, char separator ) +{ + // Remove '//' or '\\' + char *pIn = pFilename; + char *pOut = pFilename; + bool bPrevPathSep = false; + while ( *pIn ) + { + bool bIsPathSep = PATHSEPARATOR( *pIn ); + if ( !bIsPathSep || !bPrevPathSep ) + { + *pOut++ = *pIn; + } + bPrevPathSep = bIsPathSep; + ++pIn; + } + *pOut = 0; + + // Get rid of "./"'s + pIn = pFilename; + pOut = pFilename; + while ( *pIn ) + { + // The logic on the second line is preventing it from screwing up "../" + if ( pIn[0] == '.' && PATHSEPARATOR( pIn[1] ) && + (pIn == pFilename || pIn[-1] != '.') ) + { + pIn += 2; + } + else + { + *pOut = *pIn; + ++pIn; + ++pOut; + } + } + *pOut = 0; + + // Get rid of a trailing "/." (needless). + int len = strlen( pFilename ); + if ( len > 2 && pFilename[len-1] == '.' && PATHSEPARATOR( pFilename[len-2] ) ) + { + pFilename[len-2] = 0; + } + + // Each time we encounter a "..", back up until we've read the previous directory name, + // then get rid of it. + pIn = pFilename; + while ( *pIn ) + { + if ( pIn[0] == '.' && + pIn[1] == '.' && + (pIn == pFilename || PATHSEPARATOR(pIn[-1])) && // Preceding character must be a slash. + (pIn[2] == 0 || PATHSEPARATOR(pIn[2])) ) // Following character must be a slash or the end of the string. + { + char *pEndOfDots = pIn + 2; + char *pStart = pIn - 2; + + // Ok, now scan back for the path separator that starts the preceding directory. + while ( 1 ) + { + if ( pStart < pFilename ) + return false; + + if ( PATHSEPARATOR( *pStart ) ) + break; + + --pStart; + } + + // Now slide the string down to get rid of the previous directory and the ".." + memmove( pStart, pEndOfDots, strlen( pEndOfDots ) + 1 ); + + // Start over. + pIn = pFilename; + } + else + { + ++pIn; + } + } + + V_FixSlashes( pFilename, separator ); + return true; +} + + +void V_AppendSlash( char *pStr, int strSize ) +{ + int len = V_strlen( pStr ); + if ( len > 0 && !PATHSEPARATOR(pStr[len-1]) ) + { + if ( len+1 >= strSize ) + Error( "V_AppendSlash: ran out of space on %s.", pStr ); + + pStr[len] = CORRECT_PATH_SEPARATOR; + pStr[len+1] = 0; + } +} + + +void V_MakeAbsolutePath( char *pOut, int outLen, const char *pPath, const char *pStartingDir ) +{ + if ( V_IsAbsolutePath( pPath ) ) + { + // pPath is not relative.. just copy it. + V_strncpy( pOut, pPath, outLen ); + } + else + { + // Make sure the starting directory is absolute.. + if ( pStartingDir && V_IsAbsolutePath( pStartingDir ) ) + { + V_strncpy( pOut, pStartingDir, outLen ); + } + else + { + if ( !_getcwd( pOut, outLen ) ) + Error( "V_MakeAbsolutePath: _getcwd failed." ); + + if ( pStartingDir ) + { + V_AppendSlash( pOut, outLen ); + V_strncat( pOut, pStartingDir, outLen, COPY_ALL_CHARACTERS ); + } + } + + // Concatenate the paths. + V_AppendSlash( pOut, outLen ); + V_strncat( pOut, pPath, outLen, COPY_ALL_CHARACTERS ); + } + + if ( !V_RemoveDotSlashes( pOut ) ) + Error( "V_MakeAbsolutePath: tried to \"..\" past the root." ); + + V_FixSlashes( pOut ); +} + + +//----------------------------------------------------------------------------- +// Makes a relative path +//----------------------------------------------------------------------------- +bool V_MakeRelativePath( const char *pFullPath, const char *pDirectory, char *pRelativePath, int nBufLen ) +{ + pRelativePath[0] = 0; + + const char *pPath = pFullPath; + const char *pDir = pDirectory; + + // Strip out common parts of the path + const char *pLastCommonPath = NULL; + const char *pLastCommonDir = NULL; + while ( *pPath && ( tolower( *pPath ) == tolower( *pDir ) || + ( PATHSEPARATOR( *pPath ) && ( PATHSEPARATOR( *pDir ) || (*pDir == 0) ) ) ) ) + { + if ( PATHSEPARATOR( *pPath ) ) + { + pLastCommonPath = pPath + 1; + pLastCommonDir = pDir + 1; + } + if ( *pDir == 0 ) + { + --pLastCommonDir; + break; + } + ++pDir; ++pPath; + } + + // Nothing in common + if ( !pLastCommonPath ) + return false; + + // For each path separator remaining in the dir, need a ../ + int nOutLen = 0; + bool bLastCharWasSeparator = true; + for ( ; *pLastCommonDir; ++pLastCommonDir ) + { + if ( PATHSEPARATOR( *pLastCommonDir ) ) + { + pRelativePath[nOutLen++] = '.'; + pRelativePath[nOutLen++] = '.'; + pRelativePath[nOutLen++] = CORRECT_PATH_SEPARATOR; + bLastCharWasSeparator = true; + } + else + { + bLastCharWasSeparator = false; + } + } + + // Deal with relative paths not specified with a trailing slash + if ( !bLastCharWasSeparator ) + { + pRelativePath[nOutLen++] = '.'; + pRelativePath[nOutLen++] = '.'; + pRelativePath[nOutLen++] = CORRECT_PATH_SEPARATOR; + } + + // Copy the remaining part of the relative path over, fixing the path separators + for ( ; *pLastCommonPath; ++pLastCommonPath ) + { + if ( PATHSEPARATOR( *pLastCommonPath ) ) + { + pRelativePath[nOutLen++] = CORRECT_PATH_SEPARATOR; + } + else + { + pRelativePath[nOutLen++] = *pLastCommonPath; + } + + // Check for overflow + if ( nOutLen == nBufLen - 1 ) + break; + } + + pRelativePath[nOutLen] = 0; + return true; +} + + +//----------------------------------------------------------------------------- +// small helper function shared by lots of modules +//----------------------------------------------------------------------------- +bool V_IsAbsolutePath( const char *pStr ) +{ + bool bIsAbsolute = ( pStr[0] && pStr[1] == ':' ) || pStr[0] == '/' || pStr[0] == '\\'; + if ( IsX360() && !bIsAbsolute ) + { + bIsAbsolute = ( V_stristr( pStr, ":" ) != NULL ); + } + return bIsAbsolute; +} + + +// Copies at most nCharsToCopy bytes from pIn into pOut. +// Returns false if it would have overflowed pOut's buffer. +static bool CopyToMaxChars( char *pOut, int outSize, const char *pIn, int nCharsToCopy ) +{ + if ( outSize == 0 ) + return false; + + int iOut = 0; + while ( *pIn && nCharsToCopy > 0 ) + { + if ( iOut == (outSize-1) ) + { + pOut[iOut] = 0; + return false; + } + pOut[iOut] = *pIn; + ++iOut; + ++pIn; + --nCharsToCopy; + } + + pOut[iOut] = 0; + return true; +} + + +//----------------------------------------------------------------------------- +// Fixes up a file name, removing dot slashes, fixing slashes, converting to lowercase, etc. +//----------------------------------------------------------------------------- +void V_FixupPathName( char *pOut, size_t nOutLen, const char *pPath ) +{ + V_strncpy( pOut, pPath, nOutLen ); + V_FixSlashes( pOut ); + V_RemoveDotSlashes( pOut ); + V_FixDoubleSlashes( pOut ); + V_strlower( pOut ); +} + + +// Returns true if it completed successfully. +// If it would overflow pOut, it fills as much as it can and returns false. +bool V_StrSubst( + const char *pIn, + const char *pMatch, + const char *pReplaceWith, + char *pOut, + int outLen, + bool bCaseSensitive + ) +{ + int replaceFromLen = strlen( pMatch ); + int replaceToLen = strlen( pReplaceWith ); + + const char *pInStart = pIn; + char *pOutPos = pOut; + pOutPos[0] = 0; + + while ( 1 ) + { + int nRemainingOut = outLen - (pOutPos - pOut); + + const char *pTestPos = ( bCaseSensitive ? strstr( pInStart, pMatch ) : V_stristr( pInStart, pMatch ) ); + if ( pTestPos ) + { + // Found an occurence of pMatch. First, copy whatever leads up to the string. + int copyLen = pTestPos - pInStart; + if ( !CopyToMaxChars( pOutPos, nRemainingOut, pInStart, copyLen ) ) + return false; + + // Did we hit the end of the output string? + if ( copyLen > nRemainingOut-1 ) + return false; + + pOutPos += strlen( pOutPos ); + nRemainingOut = outLen - (pOutPos - pOut); + + // Now add the replacement string. + if ( !CopyToMaxChars( pOutPos, nRemainingOut, pReplaceWith, replaceToLen ) ) + return false; + + pInStart += copyLen + replaceFromLen; + pOutPos += replaceToLen; + } + else + { + // We're at the end of pIn. Copy whatever remains and get out. + int copyLen = strlen( pInStart ); + V_strncpy( pOutPos, pInStart, nRemainingOut ); + return ( copyLen <= nRemainingOut-1 ); + } + } +} + + +char* AllocString( const char *pStr, int nMaxChars ) +{ + int allocLen; + if ( nMaxChars == -1 ) + allocLen = strlen( pStr ) + 1; + else + allocLen = MIN( (int)strlen(pStr), nMaxChars ) + 1; + + char *pOut = new char[allocLen]; + V_strncpy( pOut, pStr, allocLen ); + return pOut; +} + + +void V_SplitString2( const char *pString, const char **pSeparators, int nSeparators, CUtlVector &outStrings ) +{ + outStrings.Purge(); + const char *pCurPos = pString; + while ( 1 ) + { + int iFirstSeparator = -1; + const char *pFirstSeparator = 0; + for ( int i=0; i < nSeparators; i++ ) + { + const char *pTest = V_stristr( pCurPos, pSeparators[i] ); + if ( pTest && (!pFirstSeparator || pTest < pFirstSeparator) ) + { + iFirstSeparator = i; + pFirstSeparator = pTest; + } + } + + if ( pFirstSeparator ) + { + // Split on this separator and continue on. + int separatorLen = strlen( pSeparators[iFirstSeparator] ); + if ( pFirstSeparator > pCurPos ) + { + outStrings.AddToTail( AllocString( pCurPos, pFirstSeparator-pCurPos ) ); + } + + pCurPos = pFirstSeparator + separatorLen; + } + else + { + // Copy the rest of the string + if ( strlen( pCurPos ) ) + { + outStrings.AddToTail( AllocString( pCurPos, -1 ) ); + } + return; + } + } +} + + +void V_SplitString( const char *pString, const char *pSeparator, CUtlVector &outStrings ) +{ + V_SplitString2( pString, &pSeparator, 1, outStrings ); +} + + +bool V_GetCurrentDirectory( char *pOut, int maxLen ) +{ +#if defined _LINUX || defined __APPLE__ + return getcwd( pOut, maxLen ) == pOut; +#else + return _getcwd( pOut, maxLen ) == pOut; +#endif +} + + +bool V_SetCurrentDirectory( const char *pDirName ) +{ +#if defined _LINUX || defined __APPLE__ + return chdir( pDirName ) == 0; +#else + return _chdir( pDirName ) == 0; +#endif +} + + +// This function takes a slice out of pStr and stores it in pOut. +// It follows the Python slice convention: +// Negative numbers wrap around the string (-1 references the last character). +// Numbers are clamped to the end of the string. +void V_StrSlice( const char *pStr, int firstChar, int lastCharNonInclusive, char *pOut, int outSize ) +{ + if ( outSize == 0 ) + return; + + int length = strlen( pStr ); + + // Fixup the string indices. + if ( firstChar < 0 ) + { + firstChar = length - (-firstChar % length); + } + else if ( firstChar >= length ) + { + pOut[0] = 0; + return; + } + + if ( lastCharNonInclusive < 0 ) + { + lastCharNonInclusive = length - (-lastCharNonInclusive % length); + } + else if ( lastCharNonInclusive > length ) + { + lastCharNonInclusive %= length; + } + + if ( lastCharNonInclusive <= firstChar ) + { + pOut[0] = 0; + return; + } + + int copyLen = lastCharNonInclusive - firstChar; + if ( copyLen <= (outSize-1) ) + { + memcpy( pOut, &pStr[firstChar], copyLen ); + pOut[copyLen] = 0; + } + else + { + memcpy( pOut, &pStr[firstChar], outSize-1 ); + pOut[outSize-1] = 0; + } +} + + +void V_StrLeft( const char *pStr, int nChars, char *pOut, int outSize ) +{ + if ( nChars == 0 ) + { + if ( outSize != 0 ) + pOut[0] = 0; + + return; + } + + V_StrSlice( pStr, 0, nChars, pOut, outSize ); +} + + +void V_StrRight( const char *pStr, int nChars, char *pOut, int outSize ) +{ + int len = strlen( pStr ); + if ( nChars >= len ) + { + V_strncpy( pOut, pStr, outSize ); + } + else + { + V_StrSlice( pStr, -nChars, strlen( pStr ), pOut, outSize ); + } +} + +//----------------------------------------------------------------------------- +// Convert multibyte to wchar + back +//----------------------------------------------------------------------------- +void V_strtowcs( const char *pString, int nInSize, wchar_t *pWString, int nOutSize ) +{ +#ifdef _WIN32 + if ( !MultiByteToWideChar( CP_UTF8, 0, pString, nInSize, pWString, nOutSize ) ) + { + *pWString = L'\0'; + } +#elif defined _LINUX || defined __APPLE__ + if ( mbstowcs( pWString, pString, nOutSize / sizeof(wchar_t) ) <= 0 ) + { + *pWString = 0; + } +#endif +} + +void V_wcstostr( const wchar_t *pWString, int nInSize, char *pString, int nOutSize ) +{ +#ifdef _WIN32 + if ( !WideCharToMultiByte( CP_UTF8, 0, pWString, nInSize, pString, nOutSize, NULL, NULL ) ) + { + *pString = '\0'; + } +#elif defined _LINUX || defined __APPLE__ + if ( wcstombs( pString, pWString, nOutSize ) <= 0 ) + { + *pString = '\0'; + } +#endif +} + + + +//-------------------------------------------------------------------------------- +// backslashification +//-------------------------------------------------------------------------------- + +static char s_BackSlashMap[]="\tt\nn\rr\"\"\\\\"; + +char *V_AddBackSlashesToSpecialChars( char const *pSrc ) +{ + // first, count how much space we are going to need + int nSpaceNeeded = 0; + for( char const *pScan = pSrc; *pScan; pScan++ ) + { + nSpaceNeeded++; + for(char const *pCharSet=s_BackSlashMap; *pCharSet; pCharSet += 2 ) + { + if ( *pCharSet == *pScan ) + nSpaceNeeded++; // we need to store a bakslash + } + } + char *pRet = new char[ nSpaceNeeded + 1 ]; // +1 for null + char *pOut = pRet; + + for( char const *pScan = pSrc; *pScan; pScan++ ) + { + bool bIsSpecial = false; + for(char const *pCharSet=s_BackSlashMap; *pCharSet; pCharSet += 2 ) + { + if ( *pCharSet == *pScan ) + { + *( pOut++ ) = '\\'; + *( pOut++ ) = pCharSet[1]; + bIsSpecial = true; + break; + } + } + if (! bIsSpecial ) + { + *( pOut++ ) = *pScan; + } + } + *( pOut++ ) = 0; + return pRet; +} diff --git a/tier1/tier1-2005.vcproj b/tier1/tier1-2005.vcproj new file mode 100644 index 00000000..35290bc6 --- /dev/null +++ b/tier1/tier1-2005.vcproj @@ -0,0 +1,569 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tier1/tier1.cpp b/tier1/tier1.cpp new file mode 100644 index 00000000..4b9ada6a --- /dev/null +++ b/tier1/tier1.cpp @@ -0,0 +1,63 @@ +//===== Copyright © 2005-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: A higher level link library for general use in the game and tools. +// +//===========================================================================// + +#include +#include "tier0/dbg.h" +#include "vstdlib/iprocessutils.h" +#include "icvar.h" + + +//----------------------------------------------------------------------------- +// These tier1 libraries must be set by any users of this library. +// They can be set by calling ConnectTier1Libraries or InitDefaultFileSystem. +// It is hoped that setting this, and using this library will be the common mechanism for +// allowing link libraries to access tier1 library interfaces +//----------------------------------------------------------------------------- +ICvar *cvar = 0; +ICvar *g_pCVar = 0; +IProcessUtils *g_pProcessUtils = 0; +static bool s_bConnected = false; + +// for utlsortvector.h +#ifndef _WIN32 + void *g_pUtlSortVectorQSortContext = NULL; +#endif + + +//----------------------------------------------------------------------------- +// Call this to connect to all tier 1 libraries. +// It's up to the caller to check the globals it cares about to see if ones are missing +//----------------------------------------------------------------------------- +void ConnectTier1Libraries( CreateInterfaceFn *pFactoryList, int nFactoryCount ) +{ + // Don't connect twice.. + if ( s_bConnected ) + return; + + s_bConnected = true; + + for ( int i = 0; i < nFactoryCount; ++i ) + { + if ( !g_pCVar ) + { + cvar = g_pCVar = ( ICvar * )pFactoryList[i]( CVAR_INTERFACE_VERSION, NULL ); + } + if ( !g_pProcessUtils ) + { + g_pProcessUtils = ( IProcessUtils * )pFactoryList[i]( PROCESS_UTILS_INTERFACE_VERSION, NULL ); + } + } +} + +void DisconnectTier1Libraries() +{ + if ( !s_bConnected ) + return; + + g_pCVar = cvar = 0; + g_pProcessUtils = NULL; + s_bConnected = false; +} diff --git a/tier1/tokenreader.cpp b/tier1/tokenreader.cpp new file mode 100644 index 00000000..c940e819 --- /dev/null +++ b/tier1/tokenreader.cpp @@ -0,0 +1,480 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include +#include +#include +#include "tokenreader.h" +#include "tier0/platform.h" +#include "tier1/strtools.h" +#include "tier0/dbg.h" + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +TokenReader::TokenReader(void) +{ + m_szFilename[0] = '\0'; + m_nLine = 1; + m_nErrorCount = 0; + m_bStuffed = false; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pszFilename - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool TokenReader::Open(const char *pszFilename) +{ + open(pszFilename, std::ios::in | std::ios::binary ); + Q_strncpy(m_szFilename, pszFilename, sizeof( m_szFilename ) ); + m_nLine = 1; + m_nErrorCount = 0; + m_bStuffed = false; + return(is_open() != 0); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void TokenReader::Close() +{ + close(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *error - +// Output : const char +//----------------------------------------------------------------------------- +const char *TokenReader::Error(char *error, ...) +{ + static char szErrorBuf[256]; + Q_snprintf(szErrorBuf, sizeof( szErrorBuf ), "File %s, line %d: ", m_szFilename, m_nLine); + Q_strncat(szErrorBuf, error, sizeof( szErrorBuf ), COPY_ALL_CHARACTERS ); + m_nErrorCount++; + return(szErrorBuf); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pszStore - +// nSize - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +trtoken_t TokenReader::GetString(char *pszStore, int nSize) +{ + if (nSize <= 0) + { + return TOKENERROR; + } + + char szBuf[1024]; + + // + // Until we reach the end of this string or run out of room in + // the destination buffer... + // + while (true) + { + // + // Fetch the next batch of text from the file. + // + get(szBuf, sizeof(szBuf), '\"'); + if (eof()) + { + return TOKENEOF; + } + + if (fail()) + { + // Just means nothing was read (empty string probably "") + clear(); + } + + // + // Transfer the text to the destination buffer. + // + char *pszSrc = szBuf; + while ((*pszSrc != '\0') && (nSize > 1)) + { + if (*pszSrc == 0x0d) + { + // + // Newline encountered before closing quote -- unterminated string. + // + *pszStore = '\0'; + return TOKENSTRINGTOOLONG; + } + else if (*pszSrc != '\\') + { + *pszStore = *pszSrc; + pszSrc++; + } + else + { + // + // Backslash sequence - replace with the appropriate character. + // + pszSrc++; + + if (*pszSrc == 'n') + { + *pszStore = '\n'; + } + + pszSrc++; + } + + pszStore++; + nSize--; + } + + if (*pszSrc != '\0') + { + // + // Ran out of room in the destination buffer. Skip to the close-quote, + // terminate the string, and exit. + // + ignore(1024, '\"'); + *pszStore = '\0'; + return TOKENSTRINGTOOLONG; + } + + // + // Check for closing quote. + // + if (peek() == '\"') + { + // + // Eat the close quote and any whitespace. + // + get(); + + bool bCombineStrings = SkipWhiteSpace(); + + // + // Combine consecutive quoted strings if the combine strings character was + // encountered between the two strings. + // + if (bCombineStrings && (peek() == '\"')) + { + // + // Eat the open quote and keep parsing this string. + // + get(); + } + else + { + // + // Done with this string, terminate the string and exit. + // + *pszStore = '\0'; + return STRING; + } + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns the next token, allocating enough memory to store the token +// plus a terminating NULL. +// Input : pszStore - Pointer to a string that will be allocated. +// Output : Returns the type of token that was read, or TOKENERROR. +//----------------------------------------------------------------------------- +trtoken_t TokenReader::NextTokenDynamic(char **ppszStore) +{ + char szTempBuffer[8192]; + trtoken_t eType = NextToken(szTempBuffer, sizeof(szTempBuffer)); + + int len = Q_strlen(szTempBuffer) + 1; + *ppszStore = new char [len]; + Assert( *ppszStore ); + Q_strncpy(*ppszStore, szTempBuffer, len ); + + return(eType); +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns the next token. +// Input : pszStore - Pointer to a string that will receive the token. +// Output : Returns the type of token that was read, or TOKENERROR. +//----------------------------------------------------------------------------- +trtoken_t TokenReader::NextToken(char *pszStore, int nSize) +{ + char *pStart = pszStore; + + if (!is_open()) + { + return TOKENEOF; + } + + // + // If they stuffed a token, return that token. + // + if (m_bStuffed) + { + m_bStuffed = false; + Q_strncpy( pszStore, m_szStuffed, nSize ); + return m_eStuffed; + } + + SkipWhiteSpace(); + + if (eof()) + { + return TOKENEOF; + } + + if (fail()) + { + return TOKENEOF; + } + + char ch = get(); + + // + // Look for all the valid operators. + // + switch (ch) + { + case '@': + case ',': + case '!': + case '+': + case '&': + case '*': + case '$': + case '.': + case '=': + case ':': + case '[': + case ']': + case '(': + case ')': + case '{': + case '}': + case '\\': + { + pszStore[0] = ch; + pszStore[1] = 0; + return OPERATOR; + } + } + + // + // Look for the start of a quoted string. + // + if (ch == '\"') + { + return GetString(pszStore, nSize); + } + + // + // Integers consist of numbers with an optional leading minus sign. + // + if (isdigit(ch) || (ch == '-')) + { + do + { + if ( (pszStore - pStart + 1) < nSize ) + { + *pszStore = ch; + pszStore++; + } + + ch = get(); + if (ch == '-') + { + return TOKENERROR; + } + } while (isdigit(ch)); + + // + // No identifier characters are allowed contiguous with numbers. + // + if (isalpha(ch) || (ch == '_')) + { + return TOKENERROR; + } + + // + // Put back the non-numeric character for the next call. + // + putback(ch); + *pszStore = '\0'; + return INTEGER; + } + + // + // Identifiers consist of a consecutive string of alphanumeric + // characters and underscores. + // + while ( isalpha(ch) || isdigit(ch) || (ch == '_') ) + { + if ( (pszStore - pStart + 1) < nSize ) + { + *pszStore = ch; + pszStore++; + } + + ch = get(); + } + + // + // Put back the non-identifier character for the next call. + // + putback(ch); + *pszStore = '\0'; + return IDENT; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : ttype - +// *pszToken - +//----------------------------------------------------------------------------- +void TokenReader::IgnoreTill(trtoken_t ttype, const char *pszToken) +{ + trtoken_t _ttype; + char szBuf[1024]; + + while(1) + { + _ttype = NextToken(szBuf, sizeof(szBuf)); + if(_ttype == TOKENEOF) + return; + if(_ttype == ttype) + { + if(IsToken(pszToken, szBuf)) + { + Stuff(ttype, pszToken); + return; + } + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : ttype - +// pszToken - +//----------------------------------------------------------------------------- +void TokenReader::Stuff(trtoken_t eType, const char *pszToken) +{ + m_eStuffed = eType; + Q_strncpy(m_szStuffed, pszToken, sizeof( m_szStuffed ) ); + m_bStuffed = true; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : ttype - +// pszToken - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool TokenReader::Expecting(trtoken_t ttype, const char *pszToken) +{ + char szBuf[1024]; + if (NextToken(szBuf, sizeof(szBuf)) != ttype || !IsToken(pszToken, szBuf)) + { + return false; + } + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pszStore - +// Output : +//----------------------------------------------------------------------------- +trtoken_t TokenReader::PeekTokenType(char *pszStore, int maxlen ) +{ + if (!m_bStuffed) + { + m_eStuffed = NextToken(m_szStuffed, sizeof(m_szStuffed)); + m_bStuffed = true; + } + + if (pszStore) + { + Q_strncpy(pszStore, m_szStuffed, maxlen ); + } + + return(m_eStuffed); +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets the next non-whitespace character from the file. +// Input : ch - Receives the character. +// Output : Returns true if the whitespace contained the combine strings +// character '\', which is used to merge consecutive quoted strings. +//----------------------------------------------------------------------------- +bool TokenReader::SkipWhiteSpace(void) +{ + bool bCombineStrings = false; + + while (true) + { + char ch = get(); + + if ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == 0)) + { + continue; + } + + if (ch == '+') + { + bCombineStrings = true; + continue; + } + + if (ch == '\n') + { + m_nLine++; + continue; + } + + if (eof()) + { + return(bCombineStrings); + } + + // + // Check for the start of a comment. + // + if (ch == '/') + { + if (peek() == '/') + { + ignore(1024, '\n'); + m_nLine++; + } + } + else + { + // + // It is a worthy character. Put it back. + // + putback(ch); + return(bCombineStrings); + } + } +} + diff --git a/tier1/undiff.cpp b/tier1/undiff.cpp new file mode 100644 index 00000000..e6b1a72b --- /dev/null +++ b/tier1/undiff.cpp @@ -0,0 +1,94 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// UnDiff - Apply difference block +// +//=============================================================================// + +#include "tier0/platform.h" +#include "tier0/dbg.h" +#include "tier1/diff.h" +#include "mathlib/mathlib.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +void ApplyDiffs(uint8 const *OldBlock, uint8 const *DiffList, + int OldSize, int DiffListSize, int &ResultListSize,uint8 *Output,uint32 OutSize) +{ + uint8 const *copy_src=OldBlock; + uint8 const *end_of_diff_list=DiffList+DiffListSize; + uint8 const *obuf=Output; + while(DiffList32767) + copy_ofs|=0xffff0000; + // printf("long cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz); + + memcpy(Output,copy_src+copy_ofs,copy_sz); + Output+=copy_sz; + copy_src=copy_src+copy_ofs+copy_sz; + DiffList+=4; + } + else + { + if (op & 0x80) + { + int copy_sz=op & 0x7f; + int copy_ofs; + if (copy_sz==0) + { + copy_sz=DiffList[0]; + if (copy_sz==0) + { + // big raw copy + copy_sz=DiffList[1]+256*DiffList[2]+65536*DiffList[3]; + memcpy(Output,DiffList+4,copy_sz); + // printf("big rawcopy to %x len=%d\n", Output-obuf,copy_sz); + + DiffList+=copy_sz+4; + Output+=copy_sz; + } + else + { + copy_ofs=DiffList[1]+(DiffList[2]*256); + if (copy_ofs>32767) + copy_ofs|=0xffff0000; + // printf("long ofs cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz); + + memcpy(Output,copy_src+copy_ofs,copy_sz); + Output+=copy_sz; + copy_src=copy_src+copy_ofs+copy_sz; + DiffList+=3; + } + } + else + { + copy_ofs=DiffList[0]; + if (copy_ofs>127) + copy_ofs|=0xffffff80; + // printf("cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz); + + memcpy(Output,copy_src+copy_ofs,copy_sz); + Output+=copy_sz; + copy_src=copy_src+copy_ofs+copy_sz; + DiffList++; + } + } + else + { + // printf("raw copy %d to %x\n",op & 127,Output-obuf); + memcpy(Output,DiffList,op & 127); + Output+=op & 127; + DiffList+=(op & 127); + } + } + } + ResultListSize=Output-obuf; + +} diff --git a/tier1/uniqueid.cpp b/tier1/uniqueid.cpp new file mode 100644 index 00000000..f86d0f6a --- /dev/null +++ b/tier1/uniqueid.cpp @@ -0,0 +1,177 @@ +//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======// +// +// Purpose: +// +// $NoKeywords: $ +// +// Unique ID generation +//=============================================================================// + +#include "tier0/platform.h" + +#ifdef IS_WINDOWS_PC +#include // UUIDCreate +#else +#include "checksum_crc.h" +#endif +#include "tier1/uniqueid.h" +#include "tier1/utlbuffer.h" + +//----------------------------------------------------------------------------- +// Creates a new unique id +//----------------------------------------------------------------------------- +void CreateUniqueId( UniqueId_t *pDest ) +{ +#ifdef IS_WINDOWS_PC + Assert( sizeof( UUID ) == sizeof( *pDest ) ); + UuidCreate( (UUID *)pDest ); +#else + // X360/linux TBD: Need a real UUID Implementation + Q_memset( pDest, 0, sizeof( UniqueId_t ) ); +#endif +} + + +//----------------------------------------------------------------------------- +// Creates a new unique id from a string representation of one +//----------------------------------------------------------------------------- +bool UniqueIdFromString( UniqueId_t *pDest, const char *pBuf, int nMaxLen ) +{ + if ( nMaxLen == 0 ) + { + nMaxLen = Q_strlen( pBuf ); + } + + char *pTemp = (char*)stackalloc( nMaxLen + 1 ); + V_strncpy( pTemp, pBuf, nMaxLen + 1 ); + --nMaxLen; + while( (nMaxLen >= 0) && isspace( pTemp[nMaxLen] ) ) + { + --nMaxLen; + } + pTemp[ nMaxLen + 1 ] = 0; + + while( *pTemp && isspace( *pTemp ) ) + { + ++pTemp; + } + +#ifdef IS_WINDOWS_PC + Assert( sizeof( UUID ) == sizeof( *pDest ) ); + + if ( RPC_S_OK != UuidFromString( (unsigned char *)pTemp, (UUID *)pDest ) ) + { + InvalidateUniqueId( pDest ); + return false; + } +#else + // X360TBD: Need a real UUID Implementation + // For now, use crc to generate a unique ID from the UUID string. + Q_memset( pDest, 0, sizeof( UniqueId_t ) ); + if ( nMaxLen > 0 ) + { + CRC32_t crc; + CRC32_Init( &crc ); + CRC32_ProcessBuffer( &crc, pBuf, nMaxLen ); + CRC32_Final( &crc ); + Q_memcpy( pDest, &crc, sizeof( CRC32_t ) ); + } +#endif + + return true; +} + +//----------------------------------------------------------------------------- +// Sets an object ID to be an invalid state +//----------------------------------------------------------------------------- +void InvalidateUniqueId( UniqueId_t *pDest ) +{ + Assert( pDest ); + memset( pDest, 0, sizeof( UniqueId_t ) ); +} + +bool IsUniqueIdValid( const UniqueId_t &id ) +{ + UniqueId_t invalidId; + memset( &invalidId, 0, sizeof( UniqueId_t ) ); + return !IsUniqueIdEqual( invalidId, id ); +} + +bool IsUniqueIdEqual( const UniqueId_t &id1, const UniqueId_t &id2 ) +{ + return memcmp( &id1, &id2, sizeof( UniqueId_t ) ) == 0; +} + +void UniqueIdToString( const UniqueId_t &id, char *pBuf, int nMaxLen ) +{ + pBuf[ 0 ] = 0; + +// X360TBD: Need a real UUID Implementation +#ifdef IS_WINDOWS_PC + UUID *self = ( UUID * )&id; + + unsigned char *outstring = NULL; + + UuidToString( self, &outstring ); + if ( outstring && *outstring ) + { + Q_strncpy( pBuf, (const char *)outstring, nMaxLen ); + RpcStringFree( &outstring ); + } +#endif +} + +void CopyUniqueId( const UniqueId_t &src, UniqueId_t *pDest ) +{ + memcpy( pDest, &src, sizeof( UniqueId_t ) ); +} + +bool Serialize( CUtlBuffer &buf, const UniqueId_t &src ) +{ +// X360TBD: Need a real UUID Implementation +#ifdef IS_WINDOWS_PC + if ( buf.IsText() ) + { + UUID *pId = ( UUID * )&src; + + unsigned char *outstring = NULL; + + UuidToString( pId, &outstring ); + if ( outstring && *outstring ) + { + buf.PutString( (const char *)outstring ); + RpcStringFree( &outstring ); + } + else + { + buf.PutChar( '\0' ); + } + } + else + { + buf.Put( &src, sizeof(UniqueId_t) ); + } + return buf.IsValid(); +#else + return false; +#endif +} + +bool Unserialize( CUtlBuffer &buf, UniqueId_t &dest ) +{ + if ( buf.IsText() ) + { + int nTextLen = buf.PeekStringLength(); + char *pBuf = (char*)stackalloc( nTextLen ); + buf.GetString( pBuf, nTextLen ); + UniqueIdFromString( &dest, pBuf, nTextLen ); + } + else + { + buf.Get( &dest, sizeof(UniqueId_t) ); + } + return buf.IsValid(); +} + + + diff --git a/tier1/utlbuffer.cpp b/tier1/utlbuffer.cpp new file mode 100644 index 00000000..24f99ab3 --- /dev/null +++ b/tier1/utlbuffer.cpp @@ -0,0 +1,1753 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// $Header: $ +// $NoKeywords: $ +// +// Serialization buffer +//===========================================================================// + +#ifdef _MSC_VER +#pragma warning (disable : 4514) +#endif + +#include "utlbuffer.h" +#include +#include +#include +#include +#include +#include "tier1/strtools.h" +#include "tier1/characterset.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//----------------------------------------------------------------------------- +// Character conversions for C strings +//----------------------------------------------------------------------------- +class CUtlCStringConversion : public CUtlCharConversion +{ +public: + CUtlCStringConversion( char nEscapeChar, const char *pDelimiter, int nCount, ConversionArray_t *pArray ); + + // Finds a conversion for the passed-in string, returns length + virtual char FindConversion( const char *pString, int *pLength ); + +private: + char m_pConversion[255]; +}; + + +//----------------------------------------------------------------------------- +// Character conversions for no-escape sequence strings +//----------------------------------------------------------------------------- +class CUtlNoEscConversion : public CUtlCharConversion +{ +public: + CUtlNoEscConversion( char nEscapeChar, const char *pDelimiter, int nCount, ConversionArray_t *pArray ) : + CUtlCharConversion( nEscapeChar, pDelimiter, nCount, pArray ) {} + + // Finds a conversion for the passed-in string, returns length + virtual char FindConversion( const char *pString, int *pLength ) { *pLength = 0; return 0; } +}; + + +//----------------------------------------------------------------------------- +// List of character conversions +//----------------------------------------------------------------------------- +BEGIN_CUSTOM_CHAR_CONVERSION( CUtlCStringConversion, s_StringCharConversion, "\"", '\\' ) + { '\n', "n" }, + { '\t', "t" }, + { '\v', "v" }, + { '\b', "b" }, + { '\r', "r" }, + { '\f', "f" }, + { '\a', "a" }, + { '\\', "\\" }, + { '\?', "\?" }, + { '\'', "\'" }, + { '\"', "\"" }, +END_CUSTOM_CHAR_CONVERSION( CUtlCStringConversion, s_StringCharConversion, "\"", '\\' ) + +CUtlCharConversion *GetCStringCharConversion() +{ + return &s_StringCharConversion; +} + +BEGIN_CUSTOM_CHAR_CONVERSION( CUtlNoEscConversion, s_NoEscConversion, "\"", 0x7F ) + { 0x7F, "" }, +END_CUSTOM_CHAR_CONVERSION( CUtlNoEscConversion, s_NoEscConversion, "\"", 0x7F ) + +CUtlCharConversion *GetNoEscCharConversion() +{ + return &s_NoEscConversion; +} + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CUtlCStringConversion::CUtlCStringConversion( char nEscapeChar, const char *pDelimiter, int nCount, ConversionArray_t *pArray ) : + CUtlCharConversion( nEscapeChar, pDelimiter, nCount, pArray ) +{ + memset( m_pConversion, 0x0, sizeof(m_pConversion) ); + for ( int i = 0; i < nCount; ++i ) + { + m_pConversion[ static_cast(pArray[i].m_pReplacementString[0]) ] = pArray[i].m_nActualChar; + } +} + +// Finds a conversion for the passed-in string, returns length +char CUtlCStringConversion::FindConversion( const char *pString, int *pLength ) +{ + char c = m_pConversion[ static_cast(pString[0]) ]; + *pLength = (c != '\0') ? 1 : 0; + return c; +} + + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CUtlCharConversion::CUtlCharConversion( char nEscapeChar, const char *pDelimiter, int nCount, ConversionArray_t *pArray ) +{ + m_nEscapeChar = nEscapeChar; + m_pDelimiter = pDelimiter; + m_nCount = nCount; + m_nDelimiterLength = Q_strlen( pDelimiter ); + m_nMaxConversionLength = 0; + + memset( m_pReplacements, 0, sizeof(m_pReplacements) ); + + for ( int i = 0; i < nCount; ++i ) + { + m_pList[i] = pArray[i].m_nActualChar; + ConversionInfo_t &info = m_pReplacements[ static_cast(m_pList[i]) ]; + Assert( info.m_pReplacementString == 0 ); + info.m_pReplacementString = pArray[i].m_pReplacementString; + info.m_nLength = Q_strlen( info.m_pReplacementString ); + if ( info.m_nLength > m_nMaxConversionLength ) + { + m_nMaxConversionLength = info.m_nLength; + } + } +} + + +//----------------------------------------------------------------------------- +// Escape character + delimiter +//----------------------------------------------------------------------------- +char CUtlCharConversion::GetEscapeChar() const +{ + return m_nEscapeChar; +} + +const char *CUtlCharConversion::GetDelimiter() const +{ + return m_pDelimiter; +} + +int CUtlCharConversion::GetDelimiterLength() const +{ + return m_nDelimiterLength; +} + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +const char *CUtlCharConversion::GetConversionString( char c ) const +{ + return m_pReplacements[ static_cast(c) ].m_pReplacementString; +} + +int CUtlCharConversion::GetConversionLength( char c ) const +{ + return m_pReplacements[ static_cast(c) ].m_nLength; +} + +int CUtlCharConversion::MaxConversionLength() const +{ + return m_nMaxConversionLength; +} + + +//----------------------------------------------------------------------------- +// Finds a conversion for the passed-in string, returns length +//----------------------------------------------------------------------------- +char CUtlCharConversion::FindConversion( const char *pString, int *pLength ) +{ + for ( int i = 0; i < m_nCount; ++i ) + { + if ( !Q_strcmp( pString, m_pReplacements[ static_cast(m_pList[i]) ].m_pReplacementString ) ) + { + *pLength = m_pReplacements[ static_cast(m_pList[i]) ].m_nLength; + return m_pList[i]; + } + } + + *pLength = 0; + return '\0'; +} + + +//----------------------------------------------------------------------------- +// constructors +//----------------------------------------------------------------------------- +CUtlBuffer::CUtlBuffer( int growSize, int initSize, int nFlags ) : + m_Memory( growSize, initSize ), m_Error(0) +{ + m_Get = 0; + m_Put = 0; + m_nTab = 0; + m_nOffset = 0; + m_Flags = nFlags; + if ( (initSize != 0) && !IsReadOnly() ) + { + m_nMaxPut = -1; + AddNullTermination(); + } + else + { + m_nMaxPut = 0; + } + SetOverflowFuncs( &CUtlBuffer::GetOverflow, &CUtlBuffer::PutOverflow ); +} + +CUtlBuffer::CUtlBuffer( const void *pBuffer, int nSize, int nFlags ) : + m_Memory( (unsigned char*)pBuffer, nSize ), m_Error(0) +{ + Assert( nSize != 0 ); + + m_Get = 0; + m_Put = 0; + m_nTab = 0; + m_nOffset = 0; + m_Flags = nFlags; + if ( IsReadOnly() ) + { + m_nMaxPut = nSize; + } + else + { + m_nMaxPut = -1; + AddNullTermination(); + } + SetOverflowFuncs( &CUtlBuffer::GetOverflow, &CUtlBuffer::PutOverflow ); +} + + +//----------------------------------------------------------------------------- +// Modifies the buffer to be binary or text; Blows away the buffer and the CONTAINS_CRLF value. +//----------------------------------------------------------------------------- +void CUtlBuffer::SetBufferType( bool bIsText, bool bContainsCRLF ) +{ +#ifdef _DEBUG + // If the buffer is empty, there is no opportunity for this stuff to fail + if ( TellMaxPut() != 0 ) + { + if ( IsText() ) + { + if ( bIsText ) + { + Assert( ContainsCRLF() == bContainsCRLF ); + } + else + { + Assert( ContainsCRLF() ); + } + } + else + { + if ( bIsText ) + { + Assert( bContainsCRLF ); + } + } + } +#endif + + if ( bIsText ) + { + m_Flags |= TEXT_BUFFER; + } + else + { + m_Flags &= ~TEXT_BUFFER; + } + if ( bContainsCRLF ) + { + m_Flags |= CONTAINS_CRLF; + } + else + { + m_Flags &= ~CONTAINS_CRLF; + } +} + + +//----------------------------------------------------------------------------- +// Attaches the buffer to external memory.... +//----------------------------------------------------------------------------- +void CUtlBuffer::SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags ) +{ + m_Memory.SetExternalBuffer( (unsigned char*)pMemory, nSize ); + + // Reset all indices; we just changed memory + m_Get = 0; + m_Put = nInitialPut; + m_nTab = 0; + m_Error = 0; + m_nOffset = 0; + m_Flags = nFlags; + m_nMaxPut = -1; + AddNullTermination(); +} + +//----------------------------------------------------------------------------- +// Assumes an external buffer but manages its deletion +//----------------------------------------------------------------------------- +void CUtlBuffer::AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags ) +{ + m_Memory.AssumeMemory( (unsigned char*) pMemory, nSize ); + + // Reset all indices; we just changed memory + m_Get = 0; + m_Put = nInitialPut; + m_nTab = 0; + m_Error = 0; + m_nOffset = 0; + m_Flags = nFlags; + m_nMaxPut = -1; + AddNullTermination(); +} + +//----------------------------------------------------------------------------- +// Makes sure we've got at least this much memory +//----------------------------------------------------------------------------- +void CUtlBuffer::EnsureCapacity( int num ) +{ + // Add one extra for the null termination + num += 1; + if ( m_Memory.IsExternallyAllocated() ) + { + if ( IsGrowable() && ( m_Memory.NumAllocated() < num ) ) + { + m_Memory.ConvertToGrowableMemory( 0 ); + } + else + { + num -= 1; + } + } + + m_Memory.EnsureCapacity( num ); +} + + +//----------------------------------------------------------------------------- +// Base get method from which all others derive +//----------------------------------------------------------------------------- +void CUtlBuffer::Get( void* pMem, int size ) +{ + if ( CheckGet( size ) ) + { + memcpy( pMem, &m_Memory[m_Get - m_nOffset], size ); + m_Get += size; + } +} + + +//----------------------------------------------------------------------------- +// This will get at least 1 byte and up to nSize bytes. +// It will return the number of bytes actually read. +//----------------------------------------------------------------------------- +int CUtlBuffer::GetUpTo( void *pMem, int nSize ) +{ + if ( CheckArbitraryPeekGet( 0, nSize ) ) + { + memcpy( pMem, &m_Memory[m_Get - m_nOffset], nSize ); + m_Get += nSize; + return nSize; + } + return 0; +} + + +//----------------------------------------------------------------------------- +// Eats whitespace +//----------------------------------------------------------------------------- +void CUtlBuffer::EatWhiteSpace() +{ + if ( IsText() && IsValid() ) + { + while ( CheckGet( sizeof(char) ) ) + { + if ( !isspace( *(const unsigned char*)PeekGet() ) ) + break; + m_Get += sizeof(char); + } + } +} + + +//----------------------------------------------------------------------------- +// Eats C++ style comments +//----------------------------------------------------------------------------- +bool CUtlBuffer::EatCPPComment() +{ + if ( IsText() && IsValid() ) + { + // If we don't have a a c++ style comment next, we're done + const char *pPeek = (const char *)PeekGet( 2 * sizeof(char), 0 ); + if ( !pPeek || ( pPeek[0] != '/' ) || ( pPeek[1] != '/' ) ) + return false; + + // Deal with c++ style comments + m_Get += 2; + + // read complete line + for ( char c = GetChar(); IsValid(); c = GetChar() ) + { + if ( c == '\n' ) + break; + } + return true; + } + return false; +} + + +//----------------------------------------------------------------------------- +// Peeks how much whitespace to eat +//----------------------------------------------------------------------------- +int CUtlBuffer::PeekWhiteSpace( int nOffset ) +{ + if ( !IsText() || !IsValid() ) + return 0; + + while ( CheckPeekGet( nOffset, sizeof(char) ) ) + { + if ( !isspace( *(unsigned char*)PeekGet( nOffset ) ) ) + break; + nOffset += sizeof(char); + } + + return nOffset; +} + + +//----------------------------------------------------------------------------- +// Peek size of sting to come, check memory bound +//----------------------------------------------------------------------------- +int CUtlBuffer::PeekStringLength() +{ + if ( !IsValid() ) + return 0; + + // Eat preceeding whitespace + int nOffset = 0; + if ( IsText() ) + { + nOffset = PeekWhiteSpace( nOffset ); + } + + int nStartingOffset = nOffset; + + do + { + int nPeekAmount = 128; + + // NOTE: Add 1 for the terminating zero! + if ( !CheckArbitraryPeekGet( nOffset, nPeekAmount ) ) + { + if ( nOffset == nStartingOffset ) + return 0; + return nOffset - nStartingOffset + 1; + } + + const char *pTest = (const char *)PeekGet( nOffset ); + + if ( !IsText() ) + { + for ( int i = 0; i < nPeekAmount; ++i ) + { + // The +1 here is so we eat the terminating 0 + if ( pTest[i] == 0 ) + return (i + nOffset - nStartingOffset + 1); + } + } + else + { + for ( int i = 0; i < nPeekAmount; ++i ) + { + // The +1 here is so we eat the terminating 0 + if ( isspace((unsigned char)pTest[i]) || (pTest[i] == 0) ) + return (i + nOffset - nStartingOffset + 1); + } + } + + nOffset += nPeekAmount; + + } while ( true ); +} + + +//----------------------------------------------------------------------------- +// Peek size of line to come, check memory bound +//----------------------------------------------------------------------------- +int CUtlBuffer::PeekLineLength() +{ + if ( !IsValid() ) + return 0; + + int nOffset = 0; + int nStartingOffset = nOffset; + + do + { + int nPeekAmount = 128; + + // NOTE: Add 1 for the terminating zero! + if ( !CheckArbitraryPeekGet( nOffset, nPeekAmount ) ) + { + if ( nOffset == nStartingOffset ) + return 0; + return nOffset - nStartingOffset + 1; + } + + const char *pTest = (const char *)PeekGet( nOffset ); + + for ( int i = 0; i < nPeekAmount; ++i ) + { + // The +2 here is so we eat the terminating '\n' and 0 + if ( pTest[i] == '\n' || pTest[i] == '\r' ) + return (i + nOffset - nStartingOffset + 2); + // The +1 here is so we eat the terminating 0 + if ( pTest[i] == 0 ) + return (i + nOffset - nStartingOffset + 1); + } + + nOffset += nPeekAmount; + + } while ( true ); +} + + +//----------------------------------------------------------------------------- +// Does the next bytes of the buffer match a pattern? +//----------------------------------------------------------------------------- +bool CUtlBuffer::PeekStringMatch( int nOffset, const char *pString, int nLen ) +{ + if ( !CheckPeekGet( nOffset, nLen ) ) + return false; + return !Q_strncmp( (const char*)PeekGet(nOffset), pString, nLen ); +} + + +//----------------------------------------------------------------------------- +// This version of PeekStringLength converts \" to \\ and " to \, etc. +// It also reads a " at the beginning and end of the string +//----------------------------------------------------------------------------- +int CUtlBuffer::PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActualSize ) +{ + if ( !IsText() || !pConv ) + return PeekStringLength(); + + // Eat preceeding whitespace + int nOffset = 0; + if ( IsText() ) + { + nOffset = PeekWhiteSpace( nOffset ); + } + + if ( !PeekStringMatch( nOffset, pConv->GetDelimiter(), pConv->GetDelimiterLength() ) ) + return 0; + + // Try to read ending ", but don't accept \" + int nActualStart = nOffset; + nOffset += pConv->GetDelimiterLength(); + int nLen = 1; // Starts at 1 for the '\0' termination + + do + { + if ( PeekStringMatch( nOffset, pConv->GetDelimiter(), pConv->GetDelimiterLength() ) ) + break; + + if ( !CheckPeekGet( nOffset, 1 ) ) + break; + + char c = *(const char*)PeekGet( nOffset ); + ++nLen; + ++nOffset; + if ( c == pConv->GetEscapeChar() ) + { + int nLength = pConv->MaxConversionLength(); + if ( !CheckArbitraryPeekGet( nOffset, nLength ) ) + break; + + pConv->FindConversion( (const char*)PeekGet(nOffset), &nLength ); + nOffset += nLength; + } + } while (true); + + return bActualSize ? nLen : nOffset - nActualStart + pConv->GetDelimiterLength() + 1; +} + + +//----------------------------------------------------------------------------- +// Reads a null-terminated string +//----------------------------------------------------------------------------- +void CUtlBuffer::GetString( char* pString, int nMaxChars ) +{ + if (!IsValid()) + { + *pString = 0; + return; + } + + if ( nMaxChars == 0 ) + { + nMaxChars = INT_MAX; + } + + // Remember, this *includes* the null character + // It will be 0, however, if the buffer is empty. + int nLen = PeekStringLength(); + + if ( IsText() ) + { + EatWhiteSpace(); + } + + if ( nLen == 0 ) + { + *pString = 0; + m_Error |= GET_OVERFLOW; + return; + } + + // Strip off the terminating NULL + if ( nLen <= nMaxChars ) + { + Get( pString, nLen - 1 ); + pString[ nLen - 1 ] = 0; + } + else + { + Get( pString, nMaxChars - 1 ); + pString[ nMaxChars - 1 ] = 0; + SeekGet( SEEK_CURRENT, nLen - 1 - nMaxChars ); + } + + // Read the terminating NULL in binary formats + if ( !IsText() ) + { + VerifyEquals( GetChar(), 0 ); + } +} + + +//----------------------------------------------------------------------------- +// Reads up to and including the first \n +//----------------------------------------------------------------------------- +void CUtlBuffer::GetLine( char* pLine, int nMaxChars ) +{ + Assert( IsText() && !ContainsCRLF() ); + + if ( !IsValid() ) + { + *pLine = 0; + return; + } + + if ( nMaxChars == 0 ) + { + nMaxChars = INT_MAX; + } + + // Remember, this *includes* the null character + // It will be 0, however, if the buffer is empty. + int nLen = PeekLineLength(); + if ( nLen == 0 ) + { + *pLine = 0; + m_Error |= GET_OVERFLOW; + return; + } + + // Strip off the terminating NULL + if ( nLen <= nMaxChars ) + { + Get( pLine, nLen - 1 ); + pLine[ nLen - 1 ] = 0; + } + else + { + Get( pLine, nMaxChars - 1 ); + pLine[ nMaxChars - 1 ] = 0; + SeekGet( SEEK_CURRENT, nLen - 1 - nMaxChars ); + } +} + + +//----------------------------------------------------------------------------- +// This version of GetString converts \ to \\ and " to \", etc. +// It also places " at the beginning and end of the string +//----------------------------------------------------------------------------- +char CUtlBuffer::GetDelimitedCharInternal( CUtlCharConversion *pConv ) +{ + char c = GetChar(); + if ( c == pConv->GetEscapeChar() ) + { + int nLength = pConv->MaxConversionLength(); + if ( !CheckArbitraryPeekGet( 0, nLength ) ) + return '\0'; + + c = pConv->FindConversion( (const char *)PeekGet(), &nLength ); + SeekGet( SEEK_CURRENT, nLength ); + } + + return c; +} + +char CUtlBuffer::GetDelimitedChar( CUtlCharConversion *pConv ) +{ + if ( !IsText() || !pConv ) + return GetChar( ); + return GetDelimitedCharInternal( pConv ); +} + +void CUtlBuffer::GetDelimitedString( CUtlCharConversion *pConv, char *pString, int nMaxChars ) +{ + if ( !IsText() || !pConv ) + { + GetString( pString, nMaxChars ); + return; + } + + if (!IsValid()) + { + *pString = 0; + return; + } + + if ( nMaxChars == 0 ) + { + nMaxChars = INT_MAX; + } + + EatWhiteSpace(); + if ( !PeekStringMatch( 0, pConv->GetDelimiter(), pConv->GetDelimiterLength() ) ) + return; + + // Pull off the starting delimiter + SeekGet( SEEK_CURRENT, pConv->GetDelimiterLength() ); + + int nRead = 0; + while ( IsValid() ) + { + if ( PeekStringMatch( 0, pConv->GetDelimiter(), pConv->GetDelimiterLength() ) ) + { + SeekGet( SEEK_CURRENT, pConv->GetDelimiterLength() ); + break; + } + + char c = GetDelimitedCharInternal( pConv ); + + if ( nRead < nMaxChars ) + { + pString[nRead] = c; + ++nRead; + } + } + + if ( nRead >= nMaxChars ) + { + nRead = nMaxChars - 1; + } + pString[nRead] = '\0'; +} + + +//----------------------------------------------------------------------------- +// Checks if a get is ok +//----------------------------------------------------------------------------- +bool CUtlBuffer::CheckGet( int nSize ) +{ + if ( m_Error & GET_OVERFLOW ) + return false; + + if ( TellMaxPut() < m_Get + nSize ) + { + m_Error |= GET_OVERFLOW; + return false; + } + + if ( ( m_Get < m_nOffset ) || ( m_Memory.NumAllocated() < m_Get - m_nOffset + nSize ) ) + { + if ( !OnGetOverflow( nSize ) ) + { + m_Error |= GET_OVERFLOW; + return false; + } + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Checks if a peek get is ok +//----------------------------------------------------------------------------- +bool CUtlBuffer::CheckPeekGet( int nOffset, int nSize ) +{ + if ( m_Error & GET_OVERFLOW ) + return false; + + // Checking for peek can't set the overflow flag + bool bOk = CheckGet( nOffset + nSize ); + m_Error &= ~GET_OVERFLOW; + return bOk; +} + + +//----------------------------------------------------------------------------- +// Call this to peek arbitrarily long into memory. It doesn't fail unless +// it can't read *anything* new +//----------------------------------------------------------------------------- +bool CUtlBuffer::CheckArbitraryPeekGet( int nOffset, int &nIncrement ) +{ + if ( TellGet() + nOffset >= TellMaxPut() ) + { + nIncrement = 0; + return false; + } + + if ( TellGet() + nOffset + nIncrement > TellMaxPut() ) + { + nIncrement = TellMaxPut() - TellGet() - nOffset; + } + + // NOTE: CheckPeekGet could modify TellMaxPut for streaming files + // We have to call TellMaxPut again here + CheckPeekGet( nOffset, nIncrement ); + int nMaxGet = TellMaxPut() - TellGet(); + if ( nMaxGet < nIncrement ) + { + nIncrement = nMaxGet; + } + return (nIncrement != 0); +} + + +//----------------------------------------------------------------------------- +// Peek part of the butt +//----------------------------------------------------------------------------- +const void* CUtlBuffer::PeekGet( int nMaxSize, int nOffset ) +{ + if ( !CheckPeekGet( nOffset, nMaxSize ) ) + return NULL; + return &m_Memory[ m_Get + nOffset - m_nOffset ]; +} + + +//----------------------------------------------------------------------------- +// Change where I'm reading +//----------------------------------------------------------------------------- +void CUtlBuffer::SeekGet( SeekType_t type, int offset ) +{ + switch( type ) + { + case SEEK_HEAD: + m_Get = offset; + break; + + case SEEK_CURRENT: + m_Get += offset; + break; + + case SEEK_TAIL: + m_Get = m_nMaxPut - offset; + break; + } + + if ( m_Get > m_nMaxPut ) + { + m_Error |= GET_OVERFLOW; + } + else + { + m_Error &= ~GET_OVERFLOW; + if ( m_Get < m_nOffset || m_Get >= m_nOffset + Size() ) + { + OnGetOverflow( -1 ); + } + } +} + + +//----------------------------------------------------------------------------- +// Parse... +//----------------------------------------------------------------------------- + +#ifdef _MSC_VER +#pragma warning ( disable : 4706 ) +#endif + +int CUtlBuffer::VaScanf( const char* pFmt, va_list list ) +{ + Assert( pFmt ); + if ( m_Error || !IsText() ) + return 0; + + int numScanned = 0; + int nLength; + char c; + char* pEnd; + while ( (c = *pFmt++) ) + { + // Stop if we hit the end of the buffer + if ( m_Get >= TellMaxPut() ) + { + m_Error |= GET_OVERFLOW; + break; + } + + switch (c) + { + case ' ': + // eat all whitespace + EatWhiteSpace(); + break; + + case '%': + { + // Conversion character... try to convert baby! + char type = *pFmt++; + if (type == 0) + return numScanned; + + switch(type) + { + case 'c': + { + char* ch = va_arg( list, char * ); + if ( CheckPeekGet( 0, sizeof(char) ) ) + { + *ch = *(const char*)PeekGet(); + ++m_Get; + } + else + { + *ch = 0; + return numScanned; + } + } + break; + + case 'i': + case 'd': + { + int* i = va_arg( list, int * ); + + // NOTE: This is not bullet-proof; it assumes numbers are < 128 characters + nLength = 128; + if ( !CheckArbitraryPeekGet( 0, nLength ) ) + { + *i = 0; + return numScanned; + } + + *i = strtol( (char*)PeekGet(), &pEnd, 10 ); + int nBytesRead = (int)( pEnd - (char*)PeekGet() ); + if ( nBytesRead == 0 ) + return numScanned; + m_Get += nBytesRead; + } + break; + + case 'x': + { + int* i = va_arg( list, int * ); + + // NOTE: This is not bullet-proof; it assumes numbers are < 128 characters + nLength = 128; + if ( !CheckArbitraryPeekGet( 0, nLength ) ) + { + *i = 0; + return numScanned; + } + + *i = strtol( (char*)PeekGet(), &pEnd, 16 ); + int nBytesRead = (int)( pEnd - (char*)PeekGet() ); + if ( nBytesRead == 0 ) + return numScanned; + m_Get += nBytesRead; + } + break; + + case 'u': + { + unsigned int* u = va_arg( list, unsigned int *); + + // NOTE: This is not bullet-proof; it assumes numbers are < 128 characters + nLength = 128; + if ( !CheckArbitraryPeekGet( 0, nLength ) ) + { + *u = 0; + return numScanned; + } + + *u = strtoul( (char*)PeekGet(), &pEnd, 10 ); + int nBytesRead = (int)( pEnd - (char*)PeekGet() ); + if ( nBytesRead == 0 ) + return numScanned; + m_Get += nBytesRead; + } + break; + + case 'f': + { + float* f = va_arg( list, float *); + + // NOTE: This is not bullet-proof; it assumes numbers are < 128 characters + nLength = 128; + if ( !CheckArbitraryPeekGet( 0, nLength ) ) + { + *f = 0.0f; + return numScanned; + } + + *f = (float)strtod( (char*)PeekGet(), &pEnd ); + int nBytesRead = (int)( pEnd - (char*)PeekGet() ); + if ( nBytesRead == 0 ) + return numScanned; + m_Get += nBytesRead; + } + break; + + case 's': + { + char* s = va_arg( list, char * ); + GetString( s ); + } + break; + + default: + { + // unimplemented scanf type + Assert(0); + return numScanned; + } + break; + } + + ++numScanned; + } + break; + + default: + { + // Here we have to match the format string character + // against what's in the buffer or we're done. + if ( !CheckPeekGet( 0, sizeof(char) ) ) + return numScanned; + + if ( c != *(const char*)PeekGet() ) + return numScanned; + + ++m_Get; + } + } + } + return numScanned; +} + +#ifdef _MSC_VER +#pragma warning ( default : 4706 ) +#endif + +int CUtlBuffer::Scanf( const char* pFmt, ... ) +{ + va_list args; + + va_start( args, pFmt ); + int count = VaScanf( pFmt, args ); + va_end( args ); + + return count; +} + + +//----------------------------------------------------------------------------- +// Advance the get index until after the particular string is found +// Do not eat whitespace before starting. Return false if it failed +//----------------------------------------------------------------------------- +bool CUtlBuffer::GetToken( const char *pToken ) +{ + Assert( pToken ); + + // Look for the token + int nLen = Q_strlen( pToken ); + + int nSizeToCheck = Size() - TellGet() - m_nOffset; + + int nGet = TellGet(); + do + { + int nMaxSize = TellMaxPut() - TellGet(); + if ( nMaxSize < nSizeToCheck ) + { + nSizeToCheck = nMaxSize; + } + if ( nLen > nSizeToCheck ) + break; + + if ( !CheckPeekGet( 0, nSizeToCheck ) ) + break; + + const char *pBufStart = (const char*)PeekGet(); + const char *pFoundEnd = Q_strnistr( pBufStart, pToken, nSizeToCheck ); + if ( pFoundEnd ) + { + size_t nOffset = (size_t)pFoundEnd - (size_t)pBufStart; + SeekGet( CUtlBuffer::SEEK_CURRENT, nOffset + nLen ); + return true; + } + + SeekGet( CUtlBuffer::SEEK_CURRENT, nSizeToCheck - nLen - 1 ); + nSizeToCheck = Size() - (nLen-1); + + } while ( true ); + + SeekGet( CUtlBuffer::SEEK_HEAD, nGet ); + return false; +} + + +//----------------------------------------------------------------------------- +// (For text buffers only) +// Parse a token from the buffer: +// Grab all text that lies between a starting delimiter + ending delimiter +// (skipping whitespace that leads + trails both delimiters). +// Note the delimiter checks are case-insensitive. +// If successful, the get index is advanced and the function returns true, +// otherwise the index is not advanced and the function returns false. +//----------------------------------------------------------------------------- +bool CUtlBuffer::ParseToken( const char *pStartingDelim, const char *pEndingDelim, char* pString, int nMaxLen ) +{ + int nCharsToCopy = 0; + int nCurrentGet = 0; + + size_t nEndingDelimLen; + + // Starting delimiter is optional + char emptyBuf = '\0'; + if ( !pStartingDelim ) + { + pStartingDelim = &emptyBuf; + } + + // Ending delimiter is not + Assert( pEndingDelim && pEndingDelim[0] ); + nEndingDelimLen = Q_strlen( pEndingDelim ); + + int nStartGet = TellGet(); + char nCurrChar; + int nTokenStart = -1; + EatWhiteSpace( ); + while ( *pStartingDelim ) + { + nCurrChar = *pStartingDelim++; + if ( !isspace((unsigned char)nCurrChar) ) + { + if ( tolower( GetChar() ) != tolower( nCurrChar ) ) + goto parseFailed; + } + else + { + EatWhiteSpace(); + } + } + + EatWhiteSpace(); + nTokenStart = TellGet(); + if ( !GetToken( pEndingDelim ) ) + goto parseFailed; + + nCurrentGet = TellGet(); + nCharsToCopy = (nCurrentGet - nEndingDelimLen) - nTokenStart; + if ( nCharsToCopy >= nMaxLen ) + { + nCharsToCopy = nMaxLen - 1; + } + + if ( nCharsToCopy > 0 ) + { + SeekGet( CUtlBuffer::SEEK_HEAD, nTokenStart ); + Get( pString, nCharsToCopy ); + if ( !IsValid() ) + goto parseFailed; + + // Eat trailing whitespace + for ( ; nCharsToCopy > 0; --nCharsToCopy ) + { + if ( !isspace( (unsigned char)pString[ nCharsToCopy-1 ] ) ) + break; + } + } + pString[ nCharsToCopy ] = '\0'; + + // Advance the Get index + SeekGet( CUtlBuffer::SEEK_HEAD, nCurrentGet ); + return true; + +parseFailed: + // Revert the get index + SeekGet( SEEK_HEAD, nStartGet ); + pString[0] = '\0'; + return false; +} + + +//----------------------------------------------------------------------------- +// Parses the next token, given a set of character breaks to stop at +//----------------------------------------------------------------------------- +int CUtlBuffer::ParseToken( characterset_t *pBreaks, char *pTokenBuf, int nMaxLen, bool bParseComments ) +{ + Assert( nMaxLen > 0 ); + pTokenBuf[0] = 0; + + // skip whitespace + comments + while ( true ) + { + if ( !IsValid() ) + return -1; + EatWhiteSpace(); + if ( bParseComments ) + { + if ( !EatCPPComment() ) + break; + } + else + { + break; + } + } + + char c = GetChar(); + + // End of buffer + if ( c == 0 ) + return -1; + + // handle quoted strings specially + if ( c == '\"' ) + { + int nLen = 0; + while( IsValid() ) + { + c = GetChar(); + if ( c == '\"' || !c ) + { + pTokenBuf[nLen] = 0; + return nLen; + } + pTokenBuf[nLen] = c; + if ( ++nLen == nMaxLen ) + { + pTokenBuf[nLen-1] = 0; + return nMaxLen; + } + } + + // In this case, we hit the end of the buffer before hitting the end qoute + pTokenBuf[nLen] = 0; + return nLen; + } + + // parse single characters + if ( IN_CHARACTERSET( *pBreaks, c ) ) + { + pTokenBuf[0] = c; + pTokenBuf[1] = 0; + return 1; + } + + // parse a regular word + int nLen = 0; + while ( true ) + { + pTokenBuf[nLen] = c; + if ( ++nLen == nMaxLen ) + { + pTokenBuf[nLen-1] = 0; + return nMaxLen; + } + c = GetChar(); + if ( !IsValid() ) + break; + + if ( IN_CHARACTERSET( *pBreaks, c ) || c == '\"' || c <= ' ' ) + { + SeekGet( SEEK_CURRENT, -1 ); + break; + } + } + + pTokenBuf[nLen] = 0; + return nLen; +} + + + +//----------------------------------------------------------------------------- +// Serialization +//----------------------------------------------------------------------------- +void CUtlBuffer::Put( const void *pMem, int size ) +{ + if ( size && CheckPut( size ) ) + { + memcpy( &m_Memory[m_Put - m_nOffset], pMem, size ); + m_Put += size; + + AddNullTermination(); + } +} + + +//----------------------------------------------------------------------------- +// Writes a null-terminated string +//----------------------------------------------------------------------------- +void CUtlBuffer::PutString( const char* pString ) +{ + if (!IsText()) + { + if ( pString ) + { + // Not text? append a null at the end. + size_t nLen = Q_strlen( pString ) + 1; + Put( pString, nLen * sizeof(char) ); + return; + } + else + { + PutTypeBin( 0 ); + } + } + else if (pString) + { + int nTabCount = ( m_Flags & AUTO_TABS_DISABLED ) ? 0 : m_nTab; + if ( nTabCount > 0 ) + { + if ( WasLastCharacterCR() ) + { + PutTabs(); + } + + const char* pEndl = strchr( pString, '\n' ); + while ( pEndl ) + { + size_t nSize = (size_t)pEndl - (size_t)pString + sizeof(char); + Put( pString, nSize ); + pString = pEndl + 1; + if ( *pString ) + { + PutTabs(); + pEndl = strchr( pString, '\n' ); + } + else + { + pEndl = NULL; + } + } + } + size_t nLen = Q_strlen( pString ); + if ( nLen ) + { + Put( pString, nLen * sizeof(char) ); + } + } +} + + +//----------------------------------------------------------------------------- +// This version of PutString converts \ to \\ and " to \", etc. +// It also places " at the beginning and end of the string +//----------------------------------------------------------------------------- +inline void CUtlBuffer::PutDelimitedCharInternal( CUtlCharConversion *pConv, char c ) +{ + int l = pConv->GetConversionLength( c ); + if ( l == 0 ) + { + PutChar( c ); + } + else + { + PutChar( pConv->GetEscapeChar() ); + Put( pConv->GetConversionString( c ), l ); + } +} + +void CUtlBuffer::PutDelimitedChar( CUtlCharConversion *pConv, char c ) +{ + if ( !IsText() || !pConv ) + { + PutChar( c ); + return; + } + + PutDelimitedCharInternal( pConv, c ); +} + +void CUtlBuffer::PutDelimitedString( CUtlCharConversion *pConv, const char *pString ) +{ + if ( !IsText() || !pConv ) + { + PutString( pString ); + return; + } + + if ( WasLastCharacterCR() ) + { + PutTabs(); + } + Put( pConv->GetDelimiter(), pConv->GetDelimiterLength() ); + + int nLen = pString ? Q_strlen( pString ) : 0; + for ( int i = 0; i < nLen; ++i ) + { + PutDelimitedCharInternal( pConv, pString[i] ); + } + + if ( WasLastCharacterCR() ) + { + PutTabs(); + } + Put( pConv->GetDelimiter(), pConv->GetDelimiterLength() ); +} + + +void CUtlBuffer::VaPrintf( const char* pFmt, va_list list ) +{ + char temp[2048]; +#ifdef _DEBUG + int nLen = +#endif + Q_vsnprintf( temp, sizeof( temp ), pFmt, list ); + Assert( nLen < 2048 ); + PutString( temp ); +} + +void CUtlBuffer::Printf( const char* pFmt, ... ) +{ + va_list args; + + va_start( args, pFmt ); + VaPrintf( pFmt, args ); + va_end( args ); +} + + +//----------------------------------------------------------------------------- +// Calls the overflow functions +//----------------------------------------------------------------------------- +void CUtlBuffer::SetOverflowFuncs( UtlBufferOverflowFunc_t getFunc, UtlBufferOverflowFunc_t putFunc ) +{ + m_GetOverflowFunc = getFunc; + m_PutOverflowFunc = putFunc; +} + + +//----------------------------------------------------------------------------- +// Calls the overflow functions +//----------------------------------------------------------------------------- +bool CUtlBuffer::OnPutOverflow( int nSize ) +{ + return (this->*m_PutOverflowFunc)( nSize ); +} + +bool CUtlBuffer::OnGetOverflow( int nSize ) +{ + return (this->*m_GetOverflowFunc)( nSize ); +} + + +//----------------------------------------------------------------------------- +// Checks if a put is ok +//----------------------------------------------------------------------------- +bool CUtlBuffer::PutOverflow( int nSize ) +{ + if ( m_Memory.IsExternallyAllocated() ) + { + if ( !IsGrowable() ) + return false; + + m_Memory.ConvertToGrowableMemory( 0 ); + } + + while( Size() < m_Put - m_nOffset + nSize ) + { + m_Memory.Grow(); + } + + return true; +} + +bool CUtlBuffer::GetOverflow( int nSize ) +{ + return false; +} + + +//----------------------------------------------------------------------------- +// Checks if a put is ok +//----------------------------------------------------------------------------- +bool CUtlBuffer::CheckPut( int nSize ) +{ + if ( ( m_Error & PUT_OVERFLOW ) || IsReadOnly() ) + return false; + + if ( ( m_Put < m_nOffset ) || ( m_Memory.NumAllocated() < m_Put - m_nOffset + nSize ) ) + { + if ( !OnPutOverflow( nSize ) ) + { + m_Error |= PUT_OVERFLOW; + return false; + } + } + return true; +} + +void CUtlBuffer::SeekPut( SeekType_t type, int offset ) +{ + int nNextPut = m_Put; + switch( type ) + { + case SEEK_HEAD: + nNextPut = offset; + break; + + case SEEK_CURRENT: + nNextPut += offset; + break; + + case SEEK_TAIL: + nNextPut = m_nMaxPut - offset; + break; + } + + // Force a write of the data + // FIXME: We could make this more optimal potentially by writing out + // the entire buffer if you seek outside the current range + + // NOTE: This call will write and will also seek the file to nNextPut. + OnPutOverflow( -nNextPut-1 ); + m_Put = nNextPut; + + AddNullTermination(); +} + + +void CUtlBuffer::ActivateByteSwapping( bool bActivate ) +{ + m_Byteswap.ActivateByteSwapping( bActivate ); +} + +void CUtlBuffer::SetBigEndian( bool bigEndian ) +{ + m_Byteswap.SetTargetBigEndian( bigEndian ); +} + +bool CUtlBuffer::IsBigEndian( void ) +{ + return m_Byteswap.IsTargetBigEndian(); +} + + +//----------------------------------------------------------------------------- +// null terminate the buffer +//----------------------------------------------------------------------------- +void CUtlBuffer::AddNullTermination( void ) +{ + if ( m_Put > m_nMaxPut ) + { + if ( !IsReadOnly() && ((m_Error & PUT_OVERFLOW) == 0) ) + { + // Add null termination value + if ( CheckPut( 1 ) ) + { + m_Memory[m_Put - m_nOffset] = 0; + } + else + { + // Restore the overflow state, it was valid before... + m_Error &= ~PUT_OVERFLOW; + } + } + m_nMaxPut = m_Put; + } +} + + +//----------------------------------------------------------------------------- +// Converts a buffer from a CRLF buffer to a CR buffer (and back) +// Returns false if no conversion was necessary (and outBuf is left untouched) +// If the conversion occurs, outBuf will be cleared. +//----------------------------------------------------------------------------- +bool CUtlBuffer::ConvertCRLF( CUtlBuffer &outBuf ) +{ + if ( !IsText() || !outBuf.IsText() ) + return false; + + if ( ContainsCRLF() == outBuf.ContainsCRLF() ) + return false; + + int nInCount = TellMaxPut(); + + outBuf.Purge(); + outBuf.EnsureCapacity( nInCount ); + + bool bFromCRLF = ContainsCRLF(); + + // Start reading from the beginning + int nGet = TellGet(); + int nPut = TellPut(); + int nGetDelta = 0; + int nPutDelta = 0; + + const char *pBase = (const char*)Base(); + int nCurrGet = 0; + while ( nCurrGet < nInCount ) + { + const char *pCurr = &pBase[nCurrGet]; + if ( bFromCRLF ) + { + const char *pNext = Q_strnistr( pCurr, "\r\n", nInCount - nCurrGet ); + if ( !pNext ) + { + outBuf.Put( pCurr, nInCount - nCurrGet ); + break; + } + + int nBytes = (size_t)pNext - (size_t)pCurr; + outBuf.Put( pCurr, nBytes ); + outBuf.PutChar( '\n' ); + nCurrGet += nBytes + 2; + if ( nGet >= nCurrGet - 1 ) + { + --nGetDelta; + } + if ( nPut >= nCurrGet - 1 ) + { + --nPutDelta; + } + } + else + { + const char *pNext = Q_strnchr( pCurr, '\n', nInCount - nCurrGet ); + if ( !pNext ) + { + outBuf.Put( pCurr, nInCount - nCurrGet ); + break; + } + + int nBytes = (size_t)pNext - (size_t)pCurr; + outBuf.Put( pCurr, nBytes ); + outBuf.PutChar( '\r' ); + outBuf.PutChar( '\n' ); + nCurrGet += nBytes + 1; + if ( nGet >= nCurrGet ) + { + ++nGetDelta; + } + if ( nPut >= nCurrGet ) + { + ++nPutDelta; + } + } + } + + Assert( nPut + nPutDelta <= outBuf.TellMaxPut() ); + + outBuf.SeekGet( SEEK_HEAD, nGet + nGetDelta ); + outBuf.SeekPut( SEEK_HEAD, nPut + nPutDelta ); + + return true; +} + + +//--------------------------------------------------------------------------- +// Implementation of CUtlInplaceBuffer +//--------------------------------------------------------------------------- + +CUtlInplaceBuffer::CUtlInplaceBuffer( int growSize /* = 0 */, int initSize /* = 0 */, int nFlags /* = 0 */ ) : + CUtlBuffer( growSize, initSize, nFlags ) +{ + +} + +bool CUtlInplaceBuffer::InplaceGetLinePtr( char **ppszInBufferPtr, int *pnLineLength ) +{ + Assert( IsText() && !ContainsCRLF() ); + + int nLineLen = PeekLineLength(); + if ( nLineLen <= 1 ) + { + SeekGet( SEEK_TAIL, 0 ); + return false; + } + + -- nLineLen; // because it accounts for putting a terminating null-character + + char *pszLine = ( char * ) const_cast< void * >( PeekGet() ); + SeekGet( SEEK_CURRENT, nLineLen ); + + // Set the out args + if ( ppszInBufferPtr ) + *ppszInBufferPtr = pszLine; + + if ( pnLineLength ) + *pnLineLength = nLineLen; + + return true; +} + +char * CUtlInplaceBuffer::InplaceGetLinePtr( void ) +{ + char *pszLine = NULL; + int nLineLen = 0; + + if ( InplaceGetLinePtr( &pszLine, &nLineLen ) ) + { + Assert( nLineLen >= 1 ); + + switch ( pszLine[ nLineLen - 1 ] ) + { + case '\n': + case '\r': + pszLine[ nLineLen - 1 ] = 0; + if ( -- nLineLen ) + { + switch ( pszLine[ nLineLen - 1 ] ) + { + case '\n': + case '\r': + pszLine[ nLineLen - 1 ] = 0; + break; + } + } + break; + + default: + Assert( pszLine[ nLineLen ] == 0 ); + break; + } + } + + return pszLine; +} + diff --git a/tier1/utlbufferutil.cpp b/tier1/utlbufferutil.cpp new file mode 100644 index 00000000..bffeb415 --- /dev/null +++ b/tier1/utlbufferutil.cpp @@ -0,0 +1,561 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// $Header: $ +// $NoKeywords: $ +// +// Serialization buffer +//===========================================================================// + +#ifdef _MSC_VER +#pragma warning (disable : 4514) +#endif + +#include "tier1/utlbufferutil.h" +#include "tier1/utlbuffer.h" +#include "mathlib/vector.h" +#include "mathlib/vector2d.h" +#include "mathlib/vector4d.h" +#include "mathlib/vmatrix.h" +#include "Color.h" +#include +#include +#include +#include +#include +#include "tier1/utlstring.h" +#include "tier1/strtools.h" +#include "tier1/characterset.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//----------------------------------------------------------------------------- +// For serialization, set the delimiter rules +//----------------------------------------------------------------------------- +CUtlCharConversion *s_pConv = NULL; +const char *s_pUtlBufferUtilArrayDelim = NULL; +void SetSerializationDelimiter( CUtlCharConversion *pConv ) +{ + s_pConv = pConv; +} + +void SetSerializationArrayDelimiter( const char *pDelimiter ) +{ + s_pUtlBufferUtilArrayDelim = pDelimiter; +} + + +//----------------------------------------------------------------------------- +// Serialize a floating point number in text mode in a readably friendly fashion +//----------------------------------------------------------------------------- +static void SerializeFloat( CUtlBuffer &buf, float f ) +{ + Assert( buf.IsText() ); + + // FIXME: Print this in a way that we never lose precision + char pTemp[256]; + int nLen = Q_snprintf( pTemp, sizeof(pTemp), "%.10f", f ); + while ( nLen > 0 && pTemp[nLen-1] == '0' ) + { + --nLen; + pTemp[nLen] = 0; + } + if ( nLen > 0 && pTemp[nLen-1] == '.' ) + { + --nLen; + pTemp[nLen] = 0; + } + buf.PutString( pTemp ); +} + +static void SerializeFloats( CUtlBuffer &buf, int nCount, const float *pFloats ) +{ + for ( int i = 0; i < nCount; ++i ) + { + SerializeFloat( buf, pFloats[i] ); + if ( i != nCount-1 ) + { + buf.PutChar( ' ' ); + } + } +} + + +//----------------------------------------------------------------------------- +// Serialization methods for basic types +//----------------------------------------------------------------------------- +bool Serialize( CUtlBuffer &buf, const bool &src ) +{ + if ( buf.IsText() ) + { + buf.Printf( "%d", src ); + } + else + { + buf.PutChar( src ); + } + return buf.IsValid(); +} + +bool Unserialize( CUtlBuffer &buf, bool &dest ) +{ + if ( buf.IsText() ) + { + int nValue = 0; + int nRetVal = buf.Scanf( "%d", &nValue ); + dest = ( nValue != 0 ); + return (nRetVal == 1) && buf.IsValid(); + } + + dest = ( buf.GetChar( ) != 0 ); + return buf.IsValid(); +} + + +bool Serialize( CUtlBuffer &buf, const int &src ) +{ + if ( buf.IsText() ) + { + buf.Printf( "%d", src ); + } + else + { + buf.PutInt( src ); + } + return buf.IsValid(); +} + +bool Unserialize( CUtlBuffer &buf, int &dest ) +{ + if ( buf.IsText() ) + { + int nRetVal = buf.Scanf( "%d", &dest ); + return (nRetVal == 1) && buf.IsValid(); + } + + dest = buf.GetInt( ); + return buf.IsValid(); +} + +bool Serialize( CUtlBuffer &buf, const float &src ) +{ + if ( buf.IsText() ) + { + SerializeFloat( buf, src ); + } + else + { + buf.PutFloat( src ); + } + return buf.IsValid(); +} + +bool Unserialize( CUtlBuffer &buf, float &dest ) +{ + if ( buf.IsText() ) + { + // FIXME: Print this in a way that we never lose precision + int nRetVal = buf.Scanf( "%f", &dest ); + return (nRetVal == 1) && buf.IsValid(); + } + + dest = buf.GetFloat( ); + return buf.IsValid(); +} + + +//----------------------------------------------------------------------------- +// Attribute types related to vector math +//----------------------------------------------------------------------------- +bool Serialize( CUtlBuffer &buf, const Vector2D &src ) +{ + if ( buf.IsText() ) + { + SerializeFloats( buf, 2, src.Base() ); + } + else + { + buf.PutFloat( src.x ); + buf.PutFloat( src.y ); + } + return buf.IsValid(); +} + +bool Unserialize( CUtlBuffer &buf, Vector2D &dest ) +{ + if ( buf.IsText() ) + { + // FIXME: Print this in a way that we never lose precision + int nRetVal = buf.Scanf( "%f %f", &dest.x, &dest.y ); + return (nRetVal == 2) && buf.IsValid(); + } + + dest.x = buf.GetFloat( ); + dest.y = buf.GetFloat( ); + return buf.IsValid(); +} + +bool Serialize( CUtlBuffer &buf, const Vector &src ) +{ + if ( buf.IsText() ) + { + SerializeFloats( buf, 3, src.Base() ); + } + else + { + buf.PutFloat( src.x ); + buf.PutFloat( src.y ); + buf.PutFloat( src.z ); + } + return buf.IsValid(); +} + +bool Unserialize( CUtlBuffer &buf, Vector &dest ) +{ + if ( buf.IsText() ) + { + // FIXME: Print this in a way that we never lose precision + int nRetVal = buf.Scanf( "%f %f %f", &dest.x, &dest.y, &dest.z ); + return (nRetVal == 3) && buf.IsValid(); + } + + dest.x = buf.GetFloat( ); + dest.y = buf.GetFloat( ); + dest.z = buf.GetFloat( ); + return buf.IsValid(); +} + +bool Serialize( CUtlBuffer &buf, const Vector4D &src ) +{ + if ( buf.IsText() ) + { + SerializeFloats( buf, 4, src.Base() ); + } + else + { + buf.PutFloat( src.x ); + buf.PutFloat( src.y ); + buf.PutFloat( src.z ); + buf.PutFloat( src.w ); + } + return buf.IsValid(); +} + +bool Unserialize( CUtlBuffer &buf, Vector4D &dest ) +{ + if ( buf.IsText() ) + { + // FIXME: Print this in a way that we never lose precision + int nRetVal = buf.Scanf( "%f %f %f %f", &dest.x, &dest.y, &dest.z, &dest.w ); + return (nRetVal == 4) && buf.IsValid(); + } + + dest.x = buf.GetFloat( ); + dest.y = buf.GetFloat( ); + dest.z = buf.GetFloat( ); + dest.w = buf.GetFloat( ); + return buf.IsValid(); +} + +bool Serialize( CUtlBuffer &buf, const QAngle &src ) +{ + if ( buf.IsText() ) + { + SerializeFloats( buf, 3, src.Base() ); + } + else + { + buf.PutFloat( src.x ); + buf.PutFloat( src.y ); + buf.PutFloat( src.z ); + } + return buf.IsValid(); +} + +bool Unserialize( CUtlBuffer &buf, QAngle &dest ) +{ + if ( buf.IsText() ) + { + // FIXME: Print this in a way that we never lose precision + int nRetVal = buf.Scanf( "%f %f %f", &dest.x, &dest.y, &dest.z ); + return (nRetVal == 3) && buf.IsValid(); + } + + dest.x = buf.GetFloat( ); + dest.y = buf.GetFloat( ); + dest.z = buf.GetFloat( ); + return buf.IsValid(); +} + +bool Serialize( CUtlBuffer &buf, const Quaternion &src ) +{ + if ( buf.IsText() ) + { + SerializeFloats( buf, 4, &src.x ); + } + else + { + buf.PutFloat( src.x ); + buf.PutFloat( src.y ); + buf.PutFloat( src.z ); + buf.PutFloat( src.w ); + } + return buf.IsValid(); +} + +bool Unserialize( CUtlBuffer &buf, Quaternion &dest ) +{ + if ( buf.IsText() ) + { + // FIXME: Print this in a way that we never lose precision + int nRetVal = buf.Scanf( "%f %f %f %f", &dest.x, &dest.y, &dest.z, &dest.w ); + return (nRetVal == 4) && buf.IsValid(); + } + + dest.x = buf.GetFloat( ); + dest.y = buf.GetFloat( ); + dest.z = buf.GetFloat( ); + dest.w = buf.GetFloat( ); + return buf.IsValid(); +} + +bool Serialize( CUtlBuffer &buf, const VMatrix &src ) +{ + if ( buf.IsText() ) + { + buf.Printf( "\n" ); + SerializeFloats( buf, 4, src[0] ); + buf.Printf( "\n" ); + SerializeFloats( buf, 4, src[1] ); + buf.Printf( "\n" ); + SerializeFloats( buf, 4, src[2] ); + buf.Printf( "\n" ); + SerializeFloats( buf, 4, src[3] ); + buf.Printf( "\n" ); + } + else + { + buf.Put( &src, sizeof(VMatrix) ); + } + return buf.IsValid(); +} + +bool Unserialize( CUtlBuffer &buf, VMatrix &dest ) +{ + if ( !buf.IsValid() ) + return false; + + if ( buf.IsText() ) + { + int nRetVal = buf.Scanf( "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f", + &dest[ 0 ][ 0 ], &dest[ 0 ][ 1 ], &dest[ 0 ][ 2 ], &dest[ 0 ][ 3 ], + &dest[ 1 ][ 0 ], &dest[ 1 ][ 1 ], &dest[ 1 ][ 2 ], &dest[ 1 ][ 3 ], + &dest[ 2 ][ 0 ], &dest[ 2 ][ 1 ], &dest[ 2 ][ 2 ], &dest[ 2 ][ 3 ], + &dest[ 3 ][ 0 ], &dest[ 3 ][ 1 ], &dest[ 3 ][ 2 ], &dest[ 3 ][ 3 ] ); + return (nRetVal == 16); + } + + buf.Get( &dest, sizeof(VMatrix) ); + return true; +} + + +//----------------------------------------------------------------------------- +// Color attribute +//----------------------------------------------------------------------------- +bool Serialize( CUtlBuffer &buf, const Color &src ) +{ + if ( buf.IsText() ) + { + buf.Printf( "%d %d %d %d", src[0], src[1], src[2], src[3] ); + } + else + { + buf.PutUnsignedChar( src[0] ); + buf.PutUnsignedChar( src[1] ); + buf.PutUnsignedChar( src[2] ); + buf.PutUnsignedChar( src[3] ); + } + return buf.IsValid(); +} + +bool Unserialize( CUtlBuffer &buf, Color &dest ) +{ + if ( buf.IsText() ) + { + int r = 0, g = 0, b = 0, a = 255; + int nRetVal = buf.Scanf( "%d %d %d %d", &r, &g, &b, &a ); + dest.SetColor( r, g, b, a ); + return (nRetVal == 4) && buf.IsValid(); + } + + dest[0] = buf.GetUnsignedChar( ); + dest[1] = buf.GetUnsignedChar( ); + dest[2] = buf.GetUnsignedChar( ); + dest[3] = buf.GetUnsignedChar( ); + return buf.IsValid(); +} + +/* +//----------------------------------------------------------------------------- +// Object ID attribute +//----------------------------------------------------------------------------- +bool Serialize( CUtlBuffer &buf, const DmObjectId_t &src ) +{ + return g_pDataModel->Serialize( buf, src ); +} + +bool Unserialize( CUtlBuffer &buf, DmObjectId_t &dest ) +{ + return g_pDataModel->Unserialize( buf, &dest ); +} +*/ + +//----------------------------------------------------------------------------- +// Binary buffer attribute +//----------------------------------------------------------------------------- +bool Serialize( CUtlBuffer &buf, const CUtlBinaryBlock &src ) +{ + int nLength = src.Length(); + if ( !buf.IsText() ) + { + buf.PutInt( nLength ); + if ( nLength != 0 ) + { + buf.Put( src.Get(), nLength ); + } + return buf.IsValid(); + } + + // Writes out uuencoded binaries + for ( int i = 0; i < nLength; ++i ) + { + if ( (i % 40) == 0 ) + { + buf.PutChar( '\n' ); + } + + char b1 = src[i] & 0xF; + char b2 = src[i] >> 4; + + char c1 = ( b1 <= 9 ) ? b1 + '0' : b1 - 10 + 'A'; + char c2 = ( b2 <= 9 ) ? b2 + '0' : b2 - 10 + 'A'; + + buf.PutChar( c2 ); + buf.PutChar( c1 ); + } + + buf.PutChar( '\n' ); + return buf.IsValid(); +} + +static int CountBinaryBytes( CUtlBuffer &buf, int *pEndGet ) +{ + // This counts the number of bytes in the uuencoded text + int nStartGet = buf.TellGet(); + buf.EatWhiteSpace(); + *pEndGet = buf.TellGet(); + int nByteCount = 0; + while ( buf.IsValid() ) + { + char c1 = buf.GetChar(); + char c2 = buf.GetChar(); + + bool bIsNum1 = ( c1 >= '0' ) && ( c1 <= '9' ); + bool bIsNum2 = ( c2 >= '0' ) && ( c2 <= '9' ); + + bool bIsAlpha1 = (( c1 >= 'A' ) && ( c1 <= 'F' )) || (( c1 >= 'a' ) && ( c1 <= 'f' )); + bool bIsAlpha2 = (( c2 >= 'A' ) && ( c2 <= 'F' )) || (( c2 >= 'a' ) && ( c2 <= 'f' )); + + if ( !(bIsNum1 || bIsAlpha1) || !(bIsNum2 || bIsAlpha2) ) + break; + + buf.EatWhiteSpace(); + *pEndGet = buf.TellGet(); + ++nByteCount; + } + buf.SeekGet( CUtlBuffer::SEEK_HEAD, nStartGet ); + return nByteCount; +} + +inline static unsigned char HexCharToInt( int c1 ) +{ + if (( c1 >= '0' ) && ( c1 <= '9' )) + return c1 - '0'; + + if (( c1 >= 'A' ) && ( c1 <= 'F' )) + return 10 + c1 - 'A'; + + if (( c1 >= 'a' ) && ( c1 <= 'f' )) + return 10 + c1 - 'a'; + + return 0xFF; +} + +bool Unserialize( CUtlBuffer &buf, CUtlBinaryBlock &dest ) +{ + if ( !buf.IsText() ) + { + int nLen = buf.GetInt( ); + dest.SetLength( nLen ); + if ( dest.Length() != 0 ) + { + buf.Get( dest.Get(), dest.Length() ); + } + + if ( nLen != dest.Length() ) + { + buf.SeekGet( CUtlBuffer::SEEK_CURRENT, nLen - dest.Length() ); + return false; + } + + return buf.IsValid(); + } + + int nEndGet; + int nByteCount = CountBinaryBytes( buf, &nEndGet ); + if ( nByteCount < 0 ) + return false; + + buf.EatWhiteSpace(); + int nDest = 0; + dest.SetLength( nByteCount ); + while( buf.TellGet() < nEndGet ) + { + char c1 = buf.GetChar(); + char c2 = buf.GetChar(); + + unsigned char b1 = HexCharToInt( c1 ); + unsigned char b2 = HexCharToInt( c2 ); + if ( b1 == 0xFF || b2 == 0xFF ) + return false; + + dest[ nDest++ ] = b2 | ( b1 << 4 ); + buf.EatWhiteSpace(); + } + + return true; +} + + +//----------------------------------------------------------------------------- +// String attribute +//----------------------------------------------------------------------------- +bool Serialize( CUtlBuffer &buf, const CUtlString &src ) +{ + buf.PutDelimitedString( s_pConv, src.Get() ); + return buf.IsValid(); +} + +bool Unserialize( CUtlBuffer &buf, CUtlString &dest ) +{ + int nLen = buf.PeekDelimitedStringLength( s_pConv ); + dest.SetLength( nLen - 1 ); // -1 because the length returned includes space for \0 + buf.GetDelimitedString( s_pConv, dest.Get(), nLen ); + return buf.IsValid(); +} + + + + diff --git a/tier1/utlstring.cpp b/tier1/utlstring.cpp new file mode 100644 index 00000000..9b1647d0 --- /dev/null +++ b/tier1/utlstring.cpp @@ -0,0 +1,334 @@ +//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#include "tier1/utlstring.h" +#include "tier1/strtools.h" + + +//----------------------------------------------------------------------------- +// Base class, containing simple memory management +//----------------------------------------------------------------------------- +CUtlBinaryBlock::CUtlBinaryBlock( int growSize, int initSize ) : m_Memory( growSize, initSize ) +{ + m_nActualLength = 0; +} + +CUtlBinaryBlock::CUtlBinaryBlock( void* pMemory, int nSizeInBytes, int nInitialLength ) : m_Memory( (unsigned char*)pMemory, nSizeInBytes ) +{ + m_nActualLength = nInitialLength; +} + +CUtlBinaryBlock::CUtlBinaryBlock( const void* pMemory, int nSizeInBytes ) : m_Memory( (const unsigned char*)pMemory, nSizeInBytes ) +{ + m_nActualLength = nSizeInBytes; +} + +CUtlBinaryBlock::CUtlBinaryBlock( const CUtlBinaryBlock& src ) +{ + Set( src.Get(), src.Length() ); +} + +void CUtlBinaryBlock::Get( void *pValue, int nLen ) const +{ + Assert( nLen > 0 ); + if ( m_nActualLength < nLen ) + { + nLen = m_nActualLength; + } + + if ( nLen > 0 ) + { + memcpy( pValue, m_Memory.Base(), nLen ); + } +} + +void CUtlBinaryBlock::SetLength( int nLength ) +{ + Assert( !m_Memory.IsReadOnly() ); + + m_nActualLength = nLength; + if ( nLength > m_Memory.NumAllocated() ) + { + int nOverFlow = nLength - m_Memory.NumAllocated(); + m_Memory.Grow( nOverFlow ); + + // If the reallocation failed, clamp length + if ( nLength > m_Memory.NumAllocated() ) + { + m_nActualLength = m_Memory.NumAllocated(); + } + } + +#ifdef _DEBUG + if ( m_Memory.NumAllocated() > m_nActualLength ) + { + memset( ( ( char * )m_Memory.Base() ) + m_nActualLength, 0xEB, m_Memory.NumAllocated() - m_nActualLength ); + } +#endif +} + +void CUtlBinaryBlock::Set( const void *pValue, int nLen ) +{ + Assert( !m_Memory.IsReadOnly() ); + + if ( !pValue ) + { + nLen = 0; + } + + SetLength( nLen ); + + if ( m_nActualLength ) + { + if ( ( ( const char * )m_Memory.Base() ) >= ( ( const char * )pValue ) + nLen || + ( ( const char * )m_Memory.Base() ) + m_nActualLength <= ( ( const char * )pValue ) ) + { + memcpy( m_Memory.Base(), pValue, m_nActualLength ); + } + else + { + memmove( m_Memory.Base(), pValue, m_nActualLength ); + } + } +} + + +CUtlBinaryBlock &CUtlBinaryBlock::operator=( const CUtlBinaryBlock &src ) +{ + Assert( !m_Memory.IsReadOnly() ); + Set( src.Get(), src.Length() ); + return *this; +} + + +bool CUtlBinaryBlock::operator==( const CUtlBinaryBlock &src ) const +{ + if ( src.Length() != Length() ) + return false; + + return !memcmp( src.Get(), Get(), Length() ); +} + + +//----------------------------------------------------------------------------- +// Simple string class. +//----------------------------------------------------------------------------- +CUtlString::CUtlString() +{ +} + +CUtlString::CUtlString( const char *pString ) +{ + Set( pString ); +} + +CUtlString::CUtlString( const CUtlString& string ) +{ + Set( string.Get() ); +} + +// Attaches the string to external memory. Useful for avoiding a copy +CUtlString::CUtlString( void* pMemory, int nSizeInBytes, int nInitialLength ) : m_Storage( pMemory, nSizeInBytes, nInitialLength ) +{ +} + +CUtlString::CUtlString( const void* pMemory, int nSizeInBytes ) : m_Storage( pMemory, nSizeInBytes ) +{ +} + +void CUtlString::Set( const char *pValue ) +{ + Assert( !m_Storage.IsReadOnly() ); + int nLen = pValue ? Q_strlen(pValue) + 1 : 0; + m_Storage.Set( pValue, nLen ); +} + +// Returns strlen +int CUtlString::Length() const +{ + return m_Storage.Length() ? m_Storage.Length() - 1 : 0; +} + +// Sets the length (used to serialize into the buffer ) +void CUtlString::SetLength( int nLen ) +{ + Assert( !m_Storage.IsReadOnly() ); + + // Add 1 to account for the NULL + m_Storage.SetLength( nLen > 0 ? nLen + 1 : 0 ); +} + +const char *CUtlString::Get( ) const +{ + if ( m_Storage.Length() == 0 ) + { + return ""; + } + + return reinterpret_cast< const char* >( m_Storage.Get() ); +} + +// Converts to c-strings +CUtlString::operator const char*() const +{ + return Get(); +} + +char *CUtlString::Get() +{ + Assert( !m_Storage.IsReadOnly() ); + + if ( m_Storage.Length() == 0 ) + { + // In general, we optimise away small mallocs for empty strings + // but if you ask for the non-const bytes, they must be writable + // so we can't return "" here, like we do for the const version - jd + m_Storage.SetLength( 1 ); + m_Storage[ 0 ] = '\0'; + } + + return reinterpret_cast< char* >( m_Storage.Get() ); +} + +CUtlString &CUtlString::operator=( const CUtlString &src ) +{ + Assert( !m_Storage.IsReadOnly() ); + m_Storage = src.m_Storage; + return *this; +} + +CUtlString &CUtlString::operator=( const char *src ) +{ + Assert( !m_Storage.IsReadOnly() ); + Set( src ); + return *this; +} + +bool CUtlString::operator==( const CUtlString &src ) const +{ + return m_Storage == src.m_Storage; +} + +bool CUtlString::operator==( const char *src ) const +{ + return ( strcmp( Get(), src ) == 0 ); +} + +CUtlString &CUtlString::operator+=( const CUtlString &rhs ) +{ + Assert( !m_Storage.IsReadOnly() ); + + const int lhsLength( Length() ); + const int rhsLength( rhs.Length() ); + const int requestedLength( lhsLength + rhsLength ); + + SetLength( requestedLength ); + const int allocatedLength( Length() ); + const int copyLength( allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength ); + memcpy( Get() + lhsLength, rhs.Get(), copyLength ); + m_Storage[ allocatedLength ] = '\0'; + + return *this; +} + +CUtlString &CUtlString::operator+=( const char *rhs ) +{ + Assert( !m_Storage.IsReadOnly() ); + + const int lhsLength( Length() ); + const int rhsLength( Q_strlen( rhs ) ); + const int requestedLength( lhsLength + rhsLength ); + + SetLength( requestedLength ); + const int allocatedLength( Length() ); + const int copyLength( allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength ); + memcpy( Get() + lhsLength, rhs, copyLength ); + m_Storage[ allocatedLength ] = '\0'; + + return *this; +} + +CUtlString &CUtlString::operator+=( char c ) +{ + Assert( !m_Storage.IsReadOnly() ); + + int nLength = Length(); + SetLength( nLength + 1 ); + m_Storage[ nLength ] = c; + m_Storage[ nLength+1 ] = '\0'; + return *this; +} + +CUtlString &CUtlString::operator+=( int rhs ) +{ + Assert( !m_Storage.IsReadOnly() ); + Assert( sizeof( rhs ) == 4 ); + + char tmpBuf[ 12 ]; // Sufficient for a signed 32 bit integer [ -2147483648 to +2147483647 ] + Q_snprintf( tmpBuf, sizeof( tmpBuf ), "%d", rhs ); + tmpBuf[ sizeof( tmpBuf ) - 1 ] = '\0'; + + return operator+=( tmpBuf ); +} + +CUtlString &CUtlString::operator+=( double rhs ) +{ + Assert( !m_Storage.IsReadOnly() ); + + char tmpBuf[ 256 ]; // How big can doubles be??? Dunno. + Q_snprintf( tmpBuf, sizeof( tmpBuf ), "%lg", rhs ); + tmpBuf[ sizeof( tmpBuf ) - 1 ] = '\0'; + + return operator+=( tmpBuf ); +} + +int CUtlString::Format( const char *pFormat, ... ) +{ + Assert( !m_Storage.IsReadOnly() ); + + char tmpBuf[ 4096 ]; //< Nice big 4k buffer, as much memory as my first computer had, a Radio Shack Color Computer + + va_list marker; + + va_start( marker, pFormat ); +#ifdef _WIN32 + int len = _vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker ); +#elif defined _LINUX || defined __APPLE__ + int len = vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker ); +#else +#error "define vsnprintf type." +#endif + va_end( marker ); + + // Len < 0 represents an overflow + if( len < 0 ) + { + len = sizeof( tmpBuf ) - 1; + tmpBuf[sizeof( tmpBuf ) - 1] = 0; + } + + Set( tmpBuf ); + + return len; +} + +//----------------------------------------------------------------------------- +// Strips the trailing slash +//----------------------------------------------------------------------------- +void CUtlString::StripTrailingSlash() +{ + if ( IsEmpty() ) + return; + + int nLastChar = Length() - 1; + char c = m_Storage[ nLastChar ]; + if ( c == '\\' || c == '/' ) + { + m_Storage[ nLastChar ] = 0; + m_Storage.SetLength( m_Storage.Length() - 1 ); + } +} + diff --git a/tier1/utlsymbol.cpp b/tier1/utlsymbol.cpp new file mode 100644 index 00000000..16e56734 --- /dev/null +++ b/tier1/utlsymbol.cpp @@ -0,0 +1,397 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: Defines a symbol table +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#ifdef _MSC_VER +#pragma warning (disable:4514) +#endif + +#include "utlsymbol.h" +#include "KeyValues.h" +#include "tier0/threadtools.h" +#include "tier0/memdbgon.h" +#include "stringpool.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define INVALID_STRING_INDEX CStringPoolIndex( 0xFFFF, 0xFFFF ) + +#define MIN_STRING_POOL_SIZE 2048 + +//----------------------------------------------------------------------------- +// globals +//----------------------------------------------------------------------------- + +CUtlSymbolTableMT* CUtlSymbol::s_pSymbolTable = 0; +bool CUtlSymbol::s_bAllowStaticSymbolTable = true; + + +//----------------------------------------------------------------------------- +// symbol methods +//----------------------------------------------------------------------------- + +void CUtlSymbol::Initialize() +{ + // If this assert fails, then the module that this call is in has chosen to disallow + // use of the static symbol table. Usually, it's to prevent confusion because it's easy + // to accidentally use the global symbol table when you really want to use a specific one. + Assert( s_bAllowStaticSymbolTable ); + + // necessary to allow us to create global symbols + static bool symbolsInitialized = false; + if (!symbolsInitialized) + { + s_pSymbolTable = new CUtlSymbolTableMT; + symbolsInitialized = true; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Singleton to delete table on exit from module +//----------------------------------------------------------------------------- +class CCleanupUtlSymbolTable +{ +public: + ~CCleanupUtlSymbolTable() + { + delete CUtlSymbol::s_pSymbolTable; + CUtlSymbol::s_pSymbolTable = NULL; + } +}; + +static CCleanupUtlSymbolTable g_CleanupSymbolTable; + +CUtlSymbolTableMT* CUtlSymbol::CurrTable() +{ + Initialize(); + return s_pSymbolTable; +} + + +//----------------------------------------------------------------------------- +// string->symbol->string +//----------------------------------------------------------------------------- + +CUtlSymbol::CUtlSymbol( const char* pStr ) +{ + m_Id = CurrTable()->AddString( pStr ); +} + +const char* CUtlSymbol::String( ) const +{ + return CurrTable()->String(m_Id); +} + +void CUtlSymbol::DisableStaticSymbolTable() +{ + s_bAllowStaticSymbolTable = false; +} + +//----------------------------------------------------------------------------- +// checks if the symbol matches a string +//----------------------------------------------------------------------------- + +bool CUtlSymbol::operator==( const char* pStr ) const +{ + if (m_Id == UTL_INVAL_SYMBOL) + return false; + return strcmp( String(), pStr ) == 0; +} + + + +//----------------------------------------------------------------------------- +// symbol table stuff +//----------------------------------------------------------------------------- + +inline const char* CUtlSymbolTable::StringFromIndex( const CStringPoolIndex &index ) const +{ + Assert( index.m_iPool < m_StringPools.Count() ); + Assert( index.m_iOffset < m_StringPools[index.m_iPool]->m_TotalLen ); + + return &m_StringPools[index.m_iPool]->m_Data[index.m_iOffset]; +} + + +bool CUtlSymbolTable::CLess::operator()( const CStringPoolIndex &i1, const CStringPoolIndex &i2 ) const +{ + // Need to do pointer math because CUtlSymbolTable is used in CUtlVectors, and hence + // can be arbitrarily moved in memory on a realloc. Yes, this is portable. In reality, + // right now at least, because m_LessFunc is the first member of CUtlRBTree, and m_Lookup + // is the first member of CUtlSymbolTabke, this == pTable + CUtlSymbolTable *pTable = (CUtlSymbolTable *)( (byte *)this - offsetof(CUtlSymbolTable::CTree, m_LessFunc) ) - offsetof(CUtlSymbolTable, m_Lookup ); + const char* str1 = (i1 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString : + pTable->StringFromIndex( i1 ); + const char* str2 = (i2 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString : + pTable->StringFromIndex( i2 ); + + if ( !pTable->m_bInsensitive ) + return strcmp( str1, str2 ) < 0; + else + return strcmpi( str1, str2 ) < 0; +} + + +//----------------------------------------------------------------------------- +// constructor, destructor +//----------------------------------------------------------------------------- +CUtlSymbolTable::CUtlSymbolTable( int growSize, int initSize, bool caseInsensitive ) : + m_Lookup( growSize, initSize ), m_bInsensitive( caseInsensitive ), m_StringPools( 8 ) +{ +} + +CUtlSymbolTable::~CUtlSymbolTable() +{ + // Release the stringpool string data + RemoveAll(); +} + + +CUtlSymbol CUtlSymbolTable::Find( const char* pString ) const +{ + if (!pString) + return CUtlSymbol(); + + // Store a special context used to help with insertion + m_pUserSearchString = pString; + + // Passing this special invalid symbol makes the comparison function + // use the string passed in the context + UtlSymId_t idx = m_Lookup.Find( INVALID_STRING_INDEX ); + +#ifdef _DEBUG + m_pUserSearchString = NULL; +#endif + + return CUtlSymbol( idx ); +} + + +int CUtlSymbolTable::FindPoolWithSpace( int len ) const +{ + for ( int i=0; i < m_StringPools.Count(); i++ ) + { + StringPool_t *pPool = m_StringPools[i]; + + if ( (pPool->m_TotalLen - pPool->m_SpaceUsed) >= len ) + { + return i; + } + } + + return -1; +} + + +//----------------------------------------------------------------------------- +// Finds and/or creates a symbol based on the string +//----------------------------------------------------------------------------- + +CUtlSymbol CUtlSymbolTable::AddString( const char* pString ) +{ + if (!pString) + return CUtlSymbol( UTL_INVAL_SYMBOL ); + + CUtlSymbol id = Find( pString ); + + if (id.IsValid()) + return id; + + int len = strlen(pString) + 1; + + // Find a pool with space for this string, or allocate a new one. + int iPool = FindPoolWithSpace( len ); + if ( iPool == -1 ) + { + // Add a new pool. + int newPoolSize = MAX( len, MIN_STRING_POOL_SIZE ); + StringPool_t *pPool = (StringPool_t*)malloc( sizeof( StringPool_t ) + newPoolSize - 1 ); + pPool->m_TotalLen = newPoolSize; + pPool->m_SpaceUsed = 0; + iPool = m_StringPools.AddToTail( pPool ); + } + + // Copy the string in. + StringPool_t *pPool = m_StringPools[iPool]; + Assert( pPool->m_SpaceUsed < 0xFFFF ); // This should never happen, because if we had a string > 64k, it + // would have been given its entire own pool. + + unsigned short iStringOffset = pPool->m_SpaceUsed; + + memcpy( &pPool->m_Data[pPool->m_SpaceUsed], pString, len ); + pPool->m_SpaceUsed += len; + + // didn't find, insert the string into the vector. + CStringPoolIndex index; + index.m_iPool = iPool; + index.m_iOffset = iStringOffset; + + UtlSymId_t idx = m_Lookup.Insert( index ); + return CUtlSymbol( idx ); +} + + +//----------------------------------------------------------------------------- +// Look up the string associated with a particular symbol +//----------------------------------------------------------------------------- + +const char* CUtlSymbolTable::String( CUtlSymbol id ) const +{ + if (!id.IsValid()) + return ""; + + Assert( m_Lookup.IsValidIndex((UtlSymId_t)id) ); + return StringFromIndex( m_Lookup[id] ); +} + + +//----------------------------------------------------------------------------- +// Remove all symbols in the table. +//----------------------------------------------------------------------------- + +void CUtlSymbolTable::RemoveAll() +{ + m_Lookup.Purge(); + + for ( int i=0; i < m_StringPools.Count(); i++ ) + free( m_StringPools[i] ); + + m_StringPools.RemoveAll(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pFileName - +// Output : FileNameHandle_t +//----------------------------------------------------------------------------- +FileNameHandle_t CUtlFilenameSymbolTable::FindOrAddFileName( const char *pFileName ) +{ + if ( !pFileName ) + { + return NULL; + } + + // find first + FileNameHandle_t hFileName = FindFileName( pFileName ); + if ( hFileName ) + { + return hFileName; + } + + // Fix slashes+dotslashes and make lower case first.. + char fn[ MAX_PATH ]; + Q_strncpy( fn, pFileName, sizeof( fn ) ); + Q_RemoveDotSlashes( fn ); +#ifdef _WIN32 + strlwr( fn ); +#endif + + // Split the filename into constituent parts + char basepath[ MAX_PATH ]; + Q_ExtractFilePath( fn, basepath, sizeof( basepath ) ); + char filename[ MAX_PATH ]; + Q_strncpy( filename, fn + Q_strlen( basepath ), sizeof( filename ) ); + + // not found, lock and look again + FileNameHandleInternal_t handle; + m_lock.LockForWrite(); + handle.path = m_StringPool.FindStringHandle( basepath ); + handle.file = m_StringPool.FindStringHandle( filename ); + if ( handle.path && handle.file ) + { + // found + m_lock.UnlockWrite(); + return *( FileNameHandle_t * )( &handle ); + } + + // safely add it + handle.path = m_StringPool.ReferenceStringHandle( basepath ); + handle.file = m_StringPool.ReferenceStringHandle( filename ); + m_lock.UnlockWrite(); + + return *( FileNameHandle_t * )( &handle ); +} + +FileNameHandle_t CUtlFilenameSymbolTable::FindFileName( const char *pFileName ) +{ + if ( !pFileName ) + { + return NULL; + } + + // Fix slashes+dotslashes and make lower case first.. + char fn[ MAX_PATH ]; + Q_strncpy( fn, pFileName, sizeof( fn ) ); + Q_RemoveDotSlashes( fn ); +#ifdef _WIN32 + strlwr( fn ); +#endif + + // Split the filename into constituent parts + char basepath[ MAX_PATH ]; + Q_ExtractFilePath( fn, basepath, sizeof( basepath ) ); + char filename[ MAX_PATH ]; + Q_strncpy( filename, fn + Q_strlen( basepath ), sizeof( filename ) ); + + FileNameHandleInternal_t handle; + + m_lock.LockForRead(); + handle.path = m_StringPool.FindStringHandle(basepath); + handle.file = m_StringPool.FindStringHandle(filename); + m_lock.UnlockRead(); + + if ( handle.path == 0 || handle.file == 0 ) + return NULL; + + return *( FileNameHandle_t * )( &handle ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : handle - +// Output : const char +//----------------------------------------------------------------------------- +bool CUtlFilenameSymbolTable::String( const FileNameHandle_t& handle, char *buf, int buflen ) +{ + buf[ 0 ] = 0; + + FileNameHandleInternal_t *internal = ( FileNameHandleInternal_t * )&handle; + if ( !internal ) + { + return false; + } + + m_lock.LockForRead(); + const char *path = m_StringPool.HandleToString(internal->path); + const char *fn = m_StringPool.HandleToString(internal->file); + m_lock.UnlockRead(); + + if ( !path || !fn ) + { + return false; + } + + Q_strncpy( buf, path, buflen ); + Q_strncat( buf, fn, buflen, COPY_ALL_CHARACTERS ); + + return true; +} + +void CUtlFilenameSymbolTable::RemoveAll() +{ + m_StringPool.FreeAll(); +} + +void CUtlFilenameSymbolTable::SpewStrings() +{ + m_lock.LockForRead(); + m_StringPool.SpewStrings(); + m_lock.UnlockRead(); + +} diff --git a/utils/RCBot2_meta/bot_const.h b/utils/RCBot2_meta/bot_const.h index 50e1cedc..6089d591 100644 --- a/utils/RCBot2_meta/bot_const.h +++ b/utils/RCBot2_meta/bot_const.h @@ -193,9 +193,9 @@ typedef enum #define BUILDNUM "365"*/ #define BOT_NAME "RCBot" #ifdef __linux__ -#define BOT_VER "TF2/HL2DM/DOD:S 1.04 META Linux 488-apg (merge) (BUILD " __DATE__ "-" __TIME__ ")" //bir3yk +#define BOT_VER "TF2/HL2DM/DOD:S 1.04 META Linux 490-apg (merge) (BUILD " __DATE__ "-" __TIME__ ")" //bir3yk #else -#define BOT_VER "TF2/HL2DM/DOD:S 1.04 META Win32 488-apg (merge) (BUILD " ## __DATE__ ## "-" ## __TIME__ ## ")" +#define BOT_VER "TF2/HL2DM/DOD:S 1.04 META Win32 490-apg (merge) (BUILD " ## __DATE__ ## "-" ## __TIME__ ## ")" #endif #define BOT_NAME_VER "RCbot version" #define BOT_VER_CVAR "rcbot_ver" diff --git a/utils/RCBot2_meta/bot_fortress.cpp b/utils/RCBot2_meta/bot_fortress.cpp index b92770ba..501c3460 100644 --- a/utils/RCBot2_meta/bot_fortress.cpp +++ b/utils/RCBot2_meta/bot_fortress.cpp @@ -3078,7 +3078,6 @@ void CBotTF2::modThink() m_fChangeClassTime = engine->Time() + randomFloat(bot_min_cc_time.GetFloat() / 2, bot_max_cc_time.GetFloat() / 2); } - //const int _forcedClass = rcbot_force_class.GetInt(); // Change class if either I think I could do better if (randomFloat(0.0f, 1.0f) > (scoreValue / CTeamFortress2Mod::getHighestScore())) { diff --git a/utils/RCBot2_meta/bot_perceptron.cpp b/utils/RCBot2_meta/bot_perceptron.cpp index 689ff672..2a3ded6d 100644 --- a/utils/RCBot2_meta/bot_perceptron.cpp +++ b/utils/RCBot2_meta/bot_perceptron.cpp @@ -358,7 +358,9 @@ void CBotNeuralNet :: execute ( ga_nn_value *inputs, ga_nn_value *outputs, ga_nn memset(m_layeroutput,0,sizeof(ga_nn_value)*m_numInputs); memcpy(m_layerinput,inputs,sizeof(ga_nn_value)*m_numInputs); - //pLayer = m_pHidden; + // Missing inputs!!! + for (i = 0; i < m_numInputs; i++) + m_layerinput[i] = inputs[i]; for ( l = 0; l < m_numHiddenLayers; l ++ ) { diff --git a/utils/RCBot2_meta/bot_perceptron.h b/utils/RCBot2_meta/bot_perceptron.h index d3f0c5e5..f512b5aa 100644 --- a/utils/RCBot2_meta/bot_perceptron.h +++ b/utils/RCBot2_meta/bot_perceptron.h @@ -279,7 +279,7 @@ class CBotNeuralNet { public: - CBotNeuralNet ( unsigned short int numinputs, unsigned short int hiddenlayers, unsigned short int hiddenlayer, unsigned short int outputlayer, ga_nn_value learnrate ); + CBotNeuralNet(unsigned short int numinputs, unsigned short int numhiddenlayers, unsigned short int neuronsperhiddenlayer, unsigned short int numoutputs, ga_nn_value learnrate); CBotNeuralNet () { diff --git a/utils/RCBot2_meta/bot_plugin_meta.cpp b/utils/RCBot2_meta/bot_plugin_meta.cpp index ac29eee7..72fddadb 100644 --- a/utils/RCBot2_meta/bot_plugin_meta.cpp +++ b/utils/RCBot2_meta/bot_plugin_meta.cpp @@ -1538,7 +1538,7 @@ const char *RCBotPluginMeta::GetLicense() const char *RCBotPluginMeta::GetVersion() { - return "1.01 (r487-apg-ch)"; + return "1.04 (r490-apg-ch)"; } const char *RCBotPluginMeta::GetDate() @@ -1553,7 +1553,7 @@ const char *RCBotPluginMeta::GetLogTag() const char *RCBotPluginMeta::GetAuthor() { - return "Cheeseh, RoboCop"; + return "Cheeseh, RoboCop, Ducky"; } const char *RCBotPluginMeta::GetDescription() diff --git a/utils/common/ISQLDBReplyTarget.h b/utils/common/ISQLDBReplyTarget.h new file mode 100644 index 00000000..37f88125 --- /dev/null +++ b/utils/common/ISQLDBReplyTarget.h @@ -0,0 +1,29 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef ISQLDLREPLYTARGET_H +#define ISQLDLREPLYTARGET_H +#ifdef _WIN32 +#pragma once +#endif + +//----------------------------------------------------------------------------- +// Purpose: Interface to handle results of SQL queries +//----------------------------------------------------------------------------- +class ISQLDBReplyTarget +{ +public: + // handles a response from the database + virtual void SQLDBResponse(int cmdID, int returnState, int returnVal, void *data) = 0; + + // called from a seperate thread; tells the reply target that a message is waiting for it + virtual void WakeUp() = 0; + +}; + + +#endif // ISQLDLREPLYTARGET_H diff --git a/utils/common/MySqlDatabase.cpp b/utils/common/MySqlDatabase.cpp new file mode 100644 index 00000000..803d5c26 --- /dev/null +++ b/utils/common/MySqlDatabase.cpp @@ -0,0 +1,192 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "MySqlDatabase.h" + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CMySqlDatabase::CMySqlDatabase() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +// blocks until db process thread has stopped +//----------------------------------------------------------------------------- +CMySqlDatabase::~CMySqlDatabase() +{ + // flag the thread to stop + m_bRunThread = false; + + // pulse the thread to make it run + ::SetEvent(m_hEvent); + + // make sure it's done + ::EnterCriticalSection(&m_csThread); + ::LeaveCriticalSection(&m_csThread); +} + +//----------------------------------------------------------------------------- +// Purpose: Thread access function +//----------------------------------------------------------------------------- +static DWORD WINAPI staticThreadFunc(void *param) +{ + ((CMySqlDatabase *)param)->RunThread(); + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Establishes connection to the database and sets up this object to handle db command +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CMySqlDatabase::Initialize() +{ + // prepare critical sections + //!! need to download SDK and replace these with InitializeCriticalSectionAndSpinCount() calls + ::InitializeCriticalSection(&m_csThread); + ::InitializeCriticalSection(&m_csInQueue); + ::InitializeCriticalSection(&m_csOutQueue); + ::InitializeCriticalSection(&m_csDBAccess); + + // initialize wait calls + m_hEvent = ::CreateEvent(NULL, false, true, NULL); + + // start the DB-access thread + m_bRunThread = true; + + unsigned long threadID; + ::CreateThread(NULL, 0, staticThreadFunc, this, 0, &threadID); + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Main thread loop +//----------------------------------------------------------------------------- +void CMySqlDatabase::RunThread() +{ + ::EnterCriticalSection(&m_csThread); + while (m_bRunThread) + { + if (m_InQueue.Count() > 0) + { + // get a dispatched DB request + ::EnterCriticalSection(&m_csInQueue); + + // pop the front of the queue + int headIndex = m_InQueue.Head(); + msg_t msg = m_InQueue[headIndex]; + m_InQueue.Remove(headIndex); + + ::LeaveCriticalSection(&m_csInQueue); + + ::EnterCriticalSection(&m_csDBAccess); + + // run sqldb command + msg.result = msg.cmd->RunCommand(); + + ::LeaveCriticalSection(&m_csDBAccess); + + if (msg.replyTarget) + { + // put the results in the outgoing queue + ::EnterCriticalSection(&m_csOutQueue); + m_OutQueue.AddToTail(msg); + ::LeaveCriticalSection(&m_csOutQueue); + + // wake up out queue + msg.replyTarget->WakeUp(); + } + else + { + // there is no return data from the call, so kill the object now + msg.cmd->deleteThis(); + } + } + else + { + // nothing in incoming queue, so wait until we get the signal + ::WaitForSingleObject(m_hEvent, INFINITE); + } + + // check the size of the outqueue; if it's getting too big, sleep to let the main thread catch up + if (m_OutQueue.Count() > 50) + { + ::Sleep(2); + } + } + ::LeaveCriticalSection(&m_csThread); +} + +//----------------------------------------------------------------------------- +// Purpose: Adds a database command to the queue, and wakes the db thread +//----------------------------------------------------------------------------- +void CMySqlDatabase::AddCommandToQueue(ISQLDBCommand *cmd, ISQLDBReplyTarget *replyTarget, int returnState) +{ + ::EnterCriticalSection(&m_csInQueue); + + // add to the queue + msg_t msg = { cmd, replyTarget, 0, returnState }; + m_InQueue.AddToTail(msg); + + ::LeaveCriticalSection(&m_csInQueue); + + // signal the thread to start running + ::SetEvent(m_hEvent); +} + +//----------------------------------------------------------------------------- +// Purpose: Dispatches responses to SQLDB queries +//----------------------------------------------------------------------------- +bool CMySqlDatabase::RunFrame() +{ + bool doneWork = false; + + while (m_OutQueue.Count() > 0) + { + ::EnterCriticalSection(&m_csOutQueue); + + // pop the first item in the queue + int headIndex = m_OutQueue.Head(); + msg_t msg = m_OutQueue[headIndex]; + m_OutQueue.Remove(headIndex); + + ::LeaveCriticalSection(&m_csOutQueue); + + // run result + if (msg.replyTarget) + { + msg.replyTarget->SQLDBResponse(msg.cmd->GetID(), msg.returnState, msg.result, msg.cmd->GetReturnData()); + + // kill command + // it would be a good optimization to be able to reuse these + msg.cmd->deleteThis(); + } + + doneWork = true; + } + + return doneWork; +} + +//----------------------------------------------------------------------------- +// Purpose: load info - returns the number of sql db queries waiting to be processed +//----------------------------------------------------------------------------- +int CMySqlDatabase::QueriesInOutQueue() +{ + // the queue names are from the DB point of view, not the server - thus the reversal + return m_InQueue.Count(); +} + +//----------------------------------------------------------------------------- +// Purpose: number of queries finished processing, waiting to be responded to +//----------------------------------------------------------------------------- +int CMySqlDatabase::QueriesInFinishedQueue() +{ + return m_OutQueue.Count(); +} diff --git a/utils/common/MySqlDatabase.h b/utils/common/MySqlDatabase.h new file mode 100644 index 00000000..d62c8795 --- /dev/null +++ b/utils/common/MySqlDatabase.h @@ -0,0 +1,104 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef MYSQLDATABASE_H +#define MYSQLDATABASE_H +#ifdef _WIN32 +#pragma once +#endif + +#include +#include "ISQLDBReplyTarget.h" +#include "UtlVector.h" +#include "UtlLinkedList.h" + +class ISQLDBCommand; + +//----------------------------------------------------------------------------- +// Purpose: Generic MySQL accessing database +// Provides threaded I/O queue functionality for accessing a mysql db +//----------------------------------------------------------------------------- +class CMySqlDatabase +{ +public: + // constructor + CMySqlDatabase(); + ~CMySqlDatabase(); + + // initialization - must be called before this object can be used + bool Initialize(); + + // Dispatches responses to SQLDB queries + bool RunFrame(); + + // load info - returns the number of sql db queries waiting to be processed + virtual int QueriesInOutQueue(); + + // number of queries finished processing, waiting to be responded to + virtual int QueriesInFinishedQueue(); + + // activates the thread + void RunThread(); + + // command queues + void AddCommandToQueue(ISQLDBCommand *cmd, ISQLDBReplyTarget *replyTarget, int returnState = 0); + +private: + + // threading data + bool m_bRunThread; + CRITICAL_SECTION m_csThread; + CRITICAL_SECTION m_csInQueue; + CRITICAL_SECTION m_csOutQueue; + CRITICAL_SECTION m_csDBAccess; + + // wait event + HANDLE m_hEvent; + + struct msg_t + { + ISQLDBCommand *cmd; + ISQLDBReplyTarget *replyTarget; + int result; + int returnState; + }; + + // command queues + CUtlLinkedList m_InQueue; + CUtlLinkedList m_OutQueue; +}; + +class Connection; + +//----------------------------------------------------------------------------- +// Purpose: Interface to a command +//----------------------------------------------------------------------------- +class ISQLDBCommand +{ +public: + // makes the command run (blocking), returning the success code + virtual int RunCommand() = 0; + + // return data + virtual void *GetReturnData() { return NULL; } + + // returns the command ID + virtual int GetID() { return 0; } + + // gets information about the command for if it failed + virtual void GetDebugInfo(char *buf, int bufSize) { buf[0] = 0; } + + // use to delete + virtual void deleteThis() = 0; + +protected: + // protected destructor, so that it has to be deleted through deleteThis() + virtual ~ISQLDBCommand() {} +}; + + +#endif // MYSQLDATABASE_H diff --git a/utils/common/bsplib.cpp b/utils/common/bsplib.cpp new file mode 100644 index 00000000..9db01995 --- /dev/null +++ b/utils/common/bsplib.cpp @@ -0,0 +1,2456 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Revision: $ +// $NoKeywords: $ +//=============================================================================// + +#include "cmdlib.h" +#include "mathlib.h" +#include "bsplib.h" +#include "zip_utils.h" +#include "scriplib.h" +#include "UtlLinkedList.h" +#include "BSPTreeData.h" +#include "CModel.h" +#include "GameBSPFile.h" +#include "UtlBuffer.h" +#include "UtlRBTree.h" +#include "UtlSymbol.h" +#include "checksum_crc.h" +#include "tier0/dbg.h" +#include "lumpfiles.h" + +//============================================================================= + +// "-hdr" tells us to use the HDR fields (if present) on the light sources. Also, tells us to write +// out the HDR lumps for lightmaps, ambient leaves, and lights sources. +bool g_bHDR = false; + +uint32 g_LevelFlags = 0; + +int nummodels; +dmodel_t dmodels[MAX_MAP_MODELS]; + +int visdatasize; +byte dvisdata[MAX_MAP_VISIBILITY]; +dvis_t *dvis = (dvis_t *)dvisdata; + +CUtlVector dlightdataHDR; +CUtlVector dlightdataLDR; +CUtlVector *pdlightdata = &dlightdataLDR; + +CUtlVector dentdata; + +int numleafs; +dleaf_t dleafs[MAX_MAP_LEAFS]; + +CUtlVector g_LeafAmbientLightingLDR; +CUtlVector g_LeafAmbientLightingHDR; +CUtlVector *g_pLeafAmbientLighting = NULL; // &g_LeafAmbientLightingLDR; + +unsigned short g_LeafMinDistToWater[MAX_MAP_LEAFS]; + +int numplanes; +dplane_t dplanes[MAX_MAP_PLANES]; + +int numvertexes; +dvertex_t dvertexes[MAX_MAP_VERTS]; + +int g_numvertnormalindices; // dfaces reference these. These index g_vertnormals. +unsigned short g_vertnormalindices[MAX_MAP_VERTNORMALS]; + +int g_numvertnormals; +Vector g_vertnormals[MAX_MAP_VERTNORMALS]; + +int numnodes; +dnode_t dnodes[MAX_MAP_NODES]; + +CUtlVector texinfo( MAX_MAP_TEXINFO ); + +int numtexdata; +dtexdata_t dtexdata[MAX_MAP_TEXDATA]; + +// +// displacement map bsp file info: dispinfo +// +CUtlVector g_dispinfo; +CUtlVector g_DispVerts; +CUtlVector g_DispTris; +CUtlVector g_DispLightmapSamplePositions; // LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS + +int numorigfaces; +dface_t dorigfaces[MAX_MAP_FACES]; + +int g_numprimitives = 0; +dprimitive_t g_primitives[MAX_MAP_PRIMITIVES]; + +int g_numprimverts = 0; +dprimvert_t g_primverts[MAX_MAP_PRIMVERTS]; + +int g_numprimindices = 0; +unsigned short g_primindices[MAX_MAP_PRIMINDICES]; + +int numfaces; +dface_t dfaces[MAX_MAP_FACES]; + +int numfaces_hdr; +dface_t dfaces_hdr[MAX_MAP_FACES]; + +int numedges; +dedge_t dedges[MAX_MAP_EDGES]; + +int numleaffaces; +unsigned short dleaffaces[MAX_MAP_LEAFFACES]; + +int numleafbrushes; +unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES]; + +int numsurfedges; +int dsurfedges[MAX_MAP_SURFEDGES]; + +int numbrushes; +dbrush_t dbrushes[MAX_MAP_BRUSHES]; + +int numbrushsides; +dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES]; + +int numareas; +darea_t dareas[MAX_MAP_AREAS]; + +int numareaportals; +dareaportal_t dareaportals[MAX_MAP_AREAPORTALS]; + +int numworldlightsLDR; +dworldlight_t dworldlightsLDR[MAX_MAP_WORLDLIGHTS]; + +int numworldlightsHDR; +dworldlight_t dworldlightsHDR[MAX_MAP_WORLDLIGHTS]; + +int *pNumworldlights = &numworldlightsLDR; +dworldlight_t *dworldlights = dworldlightsLDR; + +int numportals = 0; +dportal_t dportals[MAX_MAP_PORTALS]; + +int numclusters = 0; +dcluster_t dclusters[MAX_MAP_CLUSTERS]; + +int numleafwaterdata = 0; +dleafwaterdata_t dleafwaterdata[MAX_MAP_LEAFWATERDATA]; + +int numportalverts = 0; +unsigned short dportalverts[MAX_MAP_PORTALVERTS]; + +int numclusterportals; +unsigned short dclusterportals[MAX_MAP_PORTALS*2]; + +CUtlVector g_FaceMacroTextureInfos; + +Vector g_ClipPortalVerts[MAX_MAP_PORTALVERTS]; +int g_nClipPortalVerts; + +dcubemapsample_t g_CubemapSamples[MAX_MAP_CUBEMAPSAMPLES]; +int g_nCubemapSamples = 0; + +int g_nOverlayCount; +doverlay_t g_Overlays[MAX_MAP_OVERLAYS]; + +int g_nWaterOverlayCount; +dwateroverlay_t g_WaterOverlays[MAX_MAP_WATEROVERLAYS]; + +CUtlVector g_TexDataStringData; +CUtlVector g_TexDataStringTable; + +byte *g_pPhysCollide = NULL; +int g_PhysCollideSize = 0; +int g_MapRevision = 0; + +CUtlVector g_OccluderData( 256, 256 ); +CUtlVector g_OccluderPolyData( 1024, 1024 ); +CUtlVector g_OccluderVertexIndices( 2048, 2048 ); + +CUtlVector g_dLightmapPages; +CUtlVector g_dLightmapPageInfos; + +static void AddLump (int lumpnum, void *data, int len, int version = 0 ); + +dheader_t *header; +FileHandle_t wadfile; +dheader_t outheader; + +struct +{ + void *pLumps[ HEADER_LUMPS ]; + int lumpParsed[ HEADER_LUMPS ]; + int size[ HEADER_LUMPS ]; +} g_Lumps; + +//----------------------------------------------------------------------------- +// Game lump memory storage +//----------------------------------------------------------------------------- + + +// NOTE: This is not optimal at all; since I expect client lumps to +// not be accessed all that often. + +struct GameLump_t +{ + GameLumpId_t m_Id; + unsigned short m_Flags; + unsigned short m_Version; + CUtlMemory< unsigned char > m_Memory; +}; + +static CUtlLinkedList< GameLump_t, GameLumpHandle_t > s_GameLumps; + +//----------------------------------------------------------------------------- +// Purpose: // Singlegon instance +// Output : CPakFile& +//----------------------------------------------------------------------------- +IZip* GetPakFile( void ) +{ + return zip_utils; +} + +//----------------------------------------------------------------------------- +// Purpose: Set the sector alignment for all subsequent zip operations +//----------------------------------------------------------------------------- +void ForceAlignment( bool bAlign, unsigned int sectorSize ) +{ + GetPakFile()->ForceAlignment( bAlign, sectorSize ); +} + +//----------------------------------------------------------------------------- +// Purpose: Store data back out to .bsp file +//----------------------------------------------------------------------------- +static void WritePakFileLump( void ) +{ + CUtlBuffer buf( 0, 0 ); + + GetPakFile()->SaveToBuffer( buf ); + + unsigned int align = GetPakFile()->GetAlignment(); + if ( align ) + { + // must repsect pak file alignment + // pad up and ensure lump starts on same aligned boundary + int filePos = g_pFileSystem->Tell(wadfile); + int size = ((filePos + align - 1) & ~(align-1)) - filePos; + + if ( size ) + { + char *pData = (char *)malloc( size ); + memset( pData, 0, size ); + SafeWrite(wadfile, pData, size ); + free( pData ); + } + } + + // Now store final buffer out to file + AddLump( LUMP_PAKFILE, buf.Base(), buf.TellPut() ); +} + +//----------------------------------------------------------------------------- +// Purpose: Store data back out to .bsp file +//----------------------------------------------------------------------------- +static void WriteXZPPakFileLump( char* xzpFilename ) +{ + unsigned int align = 512; // HACK! + if ( align ) + { + // must repsect pak file alignment + // pad up and ensure lump starts on same aligned boundary + int filePos = g_pFileSystem->Tell(wadfile); + int size = ((filePos + align - 1) & ~(align-1)) - filePos; + + if ( size ) + { + char *pData = (char *)malloc( size ); + memset( pData, 0, size ); + SafeWrite(wadfile, pData, size ); + free( pData ); + } + } + + FILE* hXZP = fopen(xzpFilename, "rb"); + fseek(hXZP,0,SEEK_END); + int length = ftell(hXZP); + fseek(hXZP,0,SEEK_SET); + void* buffer = malloc( length ); + fread(buffer,1,length,hXZP); + fclose(hXZP); + + // Now store final buffer out to file + AddLump( LUMP_XZIPPAKFILE, buffer, length ); + free(buffer); +} + +//----------------------------------------------------------------------------- +// Purpose: Remove all entries +//----------------------------------------------------------------------------- +void ClearPackFile( void ) +{ + GetPakFile()->Reset(); +} + +//----------------------------------------------------------------------------- +// Purpose: Add file from disk to .bsp PAK lump +// Input : *relativename - +// *fullpath - +//----------------------------------------------------------------------------- +void AddFileToPack( const char *relativename, const char *fullpath ) +{ + GetPakFile()->AddFileToZip( relativename, fullpath ); +} + +//----------------------------------------------------------------------------- +// Purpose: Add buffer to .bsp PAK lump as named file +// Input : *relativename - +// *data - +// length - +//----------------------------------------------------------------------------- +void AddBufferToPack( const char *pRelativeName, void *data, int length, bool bTextMode ) +{ + GetPakFile()->AddBufferToZip( pRelativeName, data, length, bTextMode ); +} + +//----------------------------------------------------------------------------- +// Purpose: Check if a file already exists in the pack file. +// Input : *relativename - +//----------------------------------------------------------------------------- +bool FileExistsInPack( const char *pRelativeName ) +{ + return GetPakFile()->FileExistsInZip( pRelativeName ); +} + + +//----------------------------------------------------------------------------- +// Read a file from the pack file +//----------------------------------------------------------------------------- +bool ReadFileFromPack( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) +{ + return GetPakFile()->ReadFileFromZip( pRelativeName, bTextMode, buf ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Remove file from .bsp PAK lump +// Input : *relativename - +//----------------------------------------------------------------------------- +void RemoveFileFromPack( const char *relativename ) +{ + GetPakFile()->RemoveFileFromZip( relativename ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get next filename in directory +// Input : id, -1 to start, returns next id, or -1 at list conclusion +//----------------------------------------------------------------------------- +int GetNextFilename( int id, char *pBuffer, int bufferSize, int &fileSize ) +{ + return GetPakFile()->GetNextFilename( id, pBuffer, bufferSize, fileSize ); +} + + +//----------------------------------------------------------------------------- +// Convert four-CC code to a handle + back +//----------------------------------------------------------------------------- +GameLumpHandle_t GetGameLumpHandle( GameLumpId_t id ) +{ + // NOTE: I'm also expecting game lump id's to be four-CC codes + Assert( id > HEADER_LUMPS ); + + for (int i = s_GameLumps.Count(); --i >= 0; ) + { + if (s_GameLumps[i].m_Id == id) + return i; + } + + return InvalidGameLump(); +} + +GameLumpId_t GetGameLumpId( GameLumpHandle_t handle ) +{ + return s_GameLumps[handle].m_Id; +} + +int GetGameLumpFlags( GameLumpHandle_t handle ) +{ + return s_GameLumps[handle].m_Flags; +} + +int GetGameLumpVersion( GameLumpHandle_t handle ) +{ + return s_GameLumps[handle].m_Version; +} + + +//----------------------------------------------------------------------------- +// Game lump accessor methods +//----------------------------------------------------------------------------- + +void* GetGameLump( GameLumpHandle_t id ) +{ + return s_GameLumps[id].m_Memory.Base(); +} + +int GameLumpSize( GameLumpHandle_t id ) +{ + return s_GameLumps[id].m_Memory.NumAllocated(); +} + + +//----------------------------------------------------------------------------- +// Game lump iteration methods +//----------------------------------------------------------------------------- + +GameLumpHandle_t FirstGameLump() +{ + return (s_GameLumps.Count()) ? 0 : InvalidGameLump(); +} + +GameLumpHandle_t NextGameLump( GameLumpHandle_t handle ) +{ + ++handle; + return (handle < s_GameLumps.Count()) ? handle : InvalidGameLump(); +} + +GameLumpHandle_t InvalidGameLump() +{ + return 0xFFFF; +} + + +//----------------------------------------------------------------------------- +// Game lump creation/destruction method +//----------------------------------------------------------------------------- + +GameLumpHandle_t CreateGameLump( GameLumpId_t id, int size, int flags, int version ) +{ + Assert( GetGameLumpHandle(id) == InvalidGameLump() ); + GameLumpHandle_t handle = s_GameLumps.AddToTail(); + s_GameLumps[handle].m_Id = id; + s_GameLumps[handle].m_Flags = flags; + s_GameLumps[handle].m_Version = version; + s_GameLumps[handle].m_Memory.EnsureCapacity( size ); + return handle; +} + +void DestroyGameLump( GameLumpHandle_t handle ) +{ + s_GameLumps.Remove( handle ); +} + +void DestroyAllGameLumps() +{ + s_GameLumps.RemoveAll(); +} + +//----------------------------------------------------------------------------- +// String table methods +//----------------------------------------------------------------------------- +const char *TexDataStringTable_GetString( int stringID ) +{ + return &g_TexDataStringData[g_TexDataStringTable[stringID]]; +} + +int TexDataStringTable_AddOrFindString( const char *pString ) +{ + int i; + // garymcthack: Make this use an RBTree! + for( i = 0; i < g_TexDataStringTable.Count(); i++ ) + { + if( stricmp( pString, &g_TexDataStringData[g_TexDataStringTable[i]] ) == 0 ) + { + return i; + } + } + + int len = strlen( pString ); + int outOffset = g_TexDataStringData.AddMultipleToTail( len+1, pString ); + int outIndex = g_TexDataStringTable.AddToTail( outOffset ); + return outIndex; +} + +//----------------------------------------------------------------------------- +// Compute file size and clump count +//----------------------------------------------------------------------------- + +static void ComputeGameLumpSizeAndCount( int& size, int& clumpCount ) +{ + // Figure out total size of the client lumps + size = 0; + clumpCount = 0; + GameLumpHandle_t h; + for( h = FirstGameLump(); h != InvalidGameLump(); h = NextGameLump( h ) ) + { + ++clumpCount; + size += GameLumpSize( h ); + } + + // Add on headers + size += sizeof( dgamelumpheader_t ) + clumpCount * sizeof( dgamelump_t ); +} + +//----------------------------------------------------------------------------- +// Adds all game lumps into one big block +//----------------------------------------------------------------------------- + +static void AddGameLumps( ) +{ + // Figure out total size of the client lumps + int size, clumpCount; + ComputeGameLumpSizeAndCount( size, clumpCount ); + + // Set up the main lump dictionary entry + g_Lumps.size[LUMP_GAME_LUMP] = 0; // mark it written + + lump_t* lump = &header->lumps[LUMP_GAME_LUMP]; + + lump->fileofs = LittleLong( g_pFileSystem->Tell(wadfile) ); + lump->filelen = LittleLong(size); + + // write header + dgamelumpheader_t header; + header.lumpCount = clumpCount; + SafeWrite (wadfile, &header, sizeof(header)); + + // write dictionary + dgamelump_t dict; + int offset = lump->fileofs + sizeof(header) + clumpCount * sizeof(dgamelump_t); + GameLumpHandle_t h; + for( h = FirstGameLump(); h != InvalidGameLump(); h = NextGameLump( h ) ) + { + dict.id = GetGameLumpId(h); + dict.version = GetGameLumpVersion(h); + dict.flags = GetGameLumpFlags(h); + dict.fileofs = offset; + dict.filelen = GameLumpSize( h ); + SafeWrite (wadfile, &dict, sizeof(dict)); + + offset += dict.filelen; + } + + // write lumps.. + for( h = FirstGameLump(); h != InvalidGameLump(); h = NextGameLump( h ) ) + { + SafeWrite (wadfile, GetGameLump(h), GameLumpSize(h)); + } + + // align to doubleword + int totSize = (lump->filelen + 3) & ~0x3; + totSize -= lump->filelen; + if (totSize > 0) + { + char buf[3] = { 0, 0, 0 }; + SafeWrite (wadfile, buf, totSize); + } +} + + +//----------------------------------------------------------------------------- +// Game lump file I/O +//----------------------------------------------------------------------------- +static void ParseGameLump( dheader_t* pHeader ) +{ + DestroyAllGameLumps(); + + g_Lumps.lumpParsed[LUMP_GAME_LUMP] = 1; // mark it parsed + + int length = pHeader->lumps[LUMP_GAME_LUMP].filelen; + int ofs = pHeader->lumps[LUMP_GAME_LUMP].fileofs; + + if (length > 0) + { + // Read dictionary... + dgamelumpheader_t* pGameLumpHeader = (dgamelumpheader_t*)((byte *)pHeader + ofs); + dgamelump_t* pGameLump = (dgamelump_t*)(pGameLumpHeader + 1); + for (int i = 0; i < pGameLumpHeader->lumpCount; ++i ) + { + int length = pGameLump[i].filelen; + GameLumpHandle_t lump = CreateGameLump( pGameLump[i].id, length, pGameLump[i].flags, + pGameLump[i].version ); + memcpy (GetGameLump(lump), (byte *)pHeader + pGameLump[i].fileofs, length); + } + } +} + + +//----------------------------------------------------------------------------- +// Adds the occluder lump... +//----------------------------------------------------------------------------- +static void AddOcclusionLump( ) +{ + g_Lumps.size[LUMP_OCCLUSION] = 0; // mark it written + + int nOccluderCount = g_OccluderData.Count(); + int nOccluderPolyDataCount = g_OccluderPolyData.Count(); + int nOccluderVertexIndices = g_OccluderVertexIndices.Count(); + + int nLumpLength = nOccluderCount * sizeof(doccluderdata_t) + + nOccluderPolyDataCount * sizeof(doccluderpolydata_t) + + nOccluderVertexIndices * sizeof(int) + + 3 * sizeof(int); + + lump_t *lump = &header->lumps[LUMP_OCCLUSION]; + + lump->fileofs = LittleLong( g_pFileSystem->Tell(wadfile) ); + lump->filelen = LittleLong( nLumpLength ); + lump->version = LittleLong( LUMP_OCCLUSION_VERSION ); + lump->fourCC[0] = ( char )0; + lump->fourCC[1] = ( char )0; + lump->fourCC[2] = ( char )0; + lump->fourCC[3] = ( char )0; + + SafeWrite( wadfile, &nOccluderCount, 4 ); + SafeWrite( wadfile, g_OccluderData.Base(), nOccluderCount * sizeof(doccluderdata_t) ); + SafeWrite( wadfile, &nOccluderPolyDataCount, 4 ); + SafeWrite( wadfile, g_OccluderPolyData.Base(), nOccluderPolyDataCount * sizeof(doccluderpolydata_t) ); + SafeWrite( wadfile, &nOccluderVertexIndices, 4 ); + SafeWrite( wadfile, g_OccluderVertexIndices.Base(), nOccluderVertexIndices * sizeof(int) ); +} + + +//----------------------------------------------------------------------------- +// Loads the occluder lump... +//----------------------------------------------------------------------------- +static void UnserializeOcclusionLumpV2( CUtlBuffer &buf ) +{ + int nCount = buf.GetInt(); + if ( nCount ) + { + g_OccluderData.SetCount( nCount ); + buf.Get( g_OccluderData.Base(), nCount * sizeof(g_OccluderData[0]) ); + } + + nCount = buf.GetInt(); + if ( nCount ) + { + g_OccluderPolyData.SetCount( nCount ); + buf.Get( g_OccluderPolyData.Base(), nCount * sizeof(g_OccluderPolyData[0]) ); + } + + nCount = buf.GetInt(); + if ( nCount ) + { + g_OccluderVertexIndices.SetCount( nCount ); + buf.Get( g_OccluderVertexIndices.Base(), nCount * sizeof(g_OccluderVertexIndices[0]) ); + } +} + + +static void LoadOcclusionLump() +{ + g_OccluderData.RemoveAll(); + g_OccluderPolyData.RemoveAll(); + g_OccluderVertexIndices.RemoveAll(); + + int length, ofs; + + g_Lumps.lumpParsed[LUMP_OCCLUSION] = 1; // mark it parsed + + length = header->lumps[LUMP_OCCLUSION].filelen; + ofs = header->lumps[LUMP_OCCLUSION].fileofs; + + CUtlBuffer buf( (byte *)header + ofs, length, CUtlBuffer::READ_ONLY ); + switch (header->lumps[LUMP_OCCLUSION].version) + { + case 2: + UnserializeOcclusionLumpV2( buf ); + break; + + case 0: + break; + + default: + Error("Unknown occlusion lump version!\n"); + break; + } +} + + +/* +=============== +CompressVis + +=============== +*/ +int CompressVis (byte *vis, byte *dest) +{ + int j; + int rep; + int visrow; + byte *dest_p; + + dest_p = dest; +// visrow = (r_numvisleafs + 7)>>3; + visrow = (dvis->numclusters + 7)>>3; + + for (j=0 ; j>3; + row = (dvis->numclusters+7)>>3; + out = decompressed; + + do + { + if (*in) + { + *out++ = *in++; + continue; + } + + c = in[1]; + if (!c) + Error ("DecompressVis: 0 repeat"); + in += 2; + if ((out - decompressed) + c > row) + { + c = row - (out - decompressed); + Warning( "warning: Vis decompression overrun\n" ); + } + while (c) + { + *out++ = 0; + c--; + } + } while (out - decompressed < row); +} + +//============================================================================= + +int LumpVersion( int lump ) +{ + return header->lumps[lump].version; +} + +bool HasLump( int lump ) +{ + return header->lumps[lump].filelen > 0; +} + +int CopyLump (int lump, void *dest, int size, int forceVersion = -1) +{ + int length, ofs; + + g_Lumps.lumpParsed[lump] = 1; // mark it parsed + + length = header->lumps[lump].filelen; + ofs = header->lumps[lump].fileofs; + + if (length % size) + { + Error ("LoadBSPFile: odd size for lump %d", lump ); + } + + if ( forceVersion >= 0 && forceVersion != header->lumps[lump].version ) + { + Error ("LoadBSPFile: old version for lump %d in map!", lump ); + } + + memcpy (dest, (byte *)header + ofs, length); + + return length / size; +} + +template< class T > +void CopyLump ( int lump, CUtlVector &dest, int forceVersion = -1 ) +{ + int length, ofs; + + g_Lumps.lumpParsed[lump] = 1; // mark it parsed + + length = header->lumps[lump].filelen; + ofs = header->lumps[lump].fileofs; + + if (length % sizeof(T)) + { + Error ("LoadBSPFile: odd size for lump %d", lump ); + } + + if ( forceVersion >= 0 && forceVersion != header->lumps[lump].version ) + { + Error ("LoadBSPFile: old version for lump %d in map!", lump ); + } + + dest.SetSize( length / sizeof(T) ); + memcpy( dest.Base(), (byte *)header + ofs, length ); +} + +template< class T > +void CopyOptionalLump( int lump, CUtlVector &dest, int forceVersion = -1 ) +{ + int length, ofs; + + g_Lumps.lumpParsed[lump] = 1; // mark it parsed + + length = header->lumps[lump].filelen; + ofs = header->lumps[lump].fileofs; + + if (length % sizeof(T)) + { + Error ("LoadBSPFile: odd size for lump %d", lump ); + } + + // not fatal if not present + if ( length && forceVersion >= 0 && forceVersion != header->lumps[lump].version ) + { + Error ("LoadBSPFile: old version for lump %d in map!", lump ); + } + + dest.SetSize( length / sizeof(T) ); + memcpy( dest.Base(), (byte *)header + ofs, length ); +} + +int CopyVariableLump( int lump, void **dest, int size, int forceVersion = -1 ) +{ + int length, ofs; + + g_Lumps.lumpParsed[lump] = 1; // mark it parsed + + length = header->lumps[lump].filelen; + ofs = header->lumps[lump].fileofs; + + if (length % size) + { + Error ("LoadBSPFile: odd lump size"); + } + + if ( forceVersion >= 0 && forceVersion != header->lumps[lump].version ) + { + Error ("LoadBSPFile: old version map!"); + } + + *dest = malloc( length ); + memcpy (*dest, (byte *)header + ofs, length); + + return length / size; +} + +void Lumps_Init( void ) +{ + memset( &g_Lumps, 0, sizeof(g_Lumps) ); +} + +void Lumps_Parse( void ) +{ + int i; + + for ( i = 0; i < HEADER_LUMPS; i++ ) + { + if ( !g_Lumps.lumpParsed[i] && header->lumps[i].filelen ) + { + g_Lumps.size[i] = CopyVariableLump( i, &g_Lumps.pLumps[i], 1 ); + Msg("Reading unknown lump #%d (%d bytes)\n", i, g_Lumps.size[i] ); + } + } +} + +void Lumps_Write( void ) +{ + int i; + + for ( i = 0; i < HEADER_LUMPS; i++ ) + { + if ( g_Lumps.size[i] ) + { + Msg("Writing unknown lump #%d (%d bytes)\n", i, g_Lumps.size[i] ); + AddLump( i, g_Lumps.pLumps[i], g_Lumps.size[i] ); + } + if ( g_Lumps.pLumps[i] ) + { + free( g_Lumps.pLumps[i] ); + g_Lumps.pLumps[i] = NULL; + } + } +} + + +int LoadLeafs( void ) +{ + switch( LumpVersion( LUMP_LEAFS ) ) + { + case 0: + { + int length = header->lumps[LUMP_LEAFS].filelen; + g_Lumps.lumpParsed[LUMP_LEAFS] = 1; // mark it parsed + int size = sizeof( dleaf_version_0_t ); + if( length % size ) + { + Error( "odd size for LUMP_LEAFS\n" ); + } + int count = length / size; + dleaf_version_0_t *pSrc = ( dleaf_version_0_t * )( ( byte * )header + header->lumps[LUMP_LEAFS].fileofs ); + dleaf_t *pDst = dleafs; + Assert( g_pLeafAmbientLighting ); + g_pLeafAmbientLighting->SetCount( count ); + CompressedLightCube *pDstLeafAmbientLighting = &(*g_pLeafAmbientLighting)[0]; + int i; + for( i = 0; i < count; i++ ) + { + // pDst is a subset of pSrc; + *pDst = *( ( dleaf_t * )( void * )pSrc ); + *pDstLeafAmbientLighting = pSrc->m_AmbientLighting; + pDst++; + pSrc++; + pDstLeafAmbientLighting++; + } + return count; + } + break; + case 1: + return CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t)); + break; + default: + Assert( 0 ); + Error( "Unknown LUMP_LEAFS version\n" ); + return 0; + break; + } +} + +/* +============= +OpenBSPFile + +Low level BSP opener for external parsing. Parses headers, but nothing else. +You must close the BSP, via CloseBSPFile(). +============= +*/ +void OpenBSPFile (char *filename) +{ + int i; + + Lumps_Init(); + + // load the file header + LoadFile (filename, (void **)&header); + + // swap the header + for (i=0 ; i< sizeof(dheader_t)/4 ; i++) + ((int *)header)[i] = LittleLong ( ((int *)header)[i]); + + if (header->ident != IDBSPHEADER) + Error ("%s is not a IBSP file", filename); + if (header->version < MINBSPVERSION || header->version > BSPVERSION) + Error ("%s is version %i, not %i", filename, header->version, BSPVERSION); + + g_MapRevision = header->mapRevision; +} + +/* +============= +CloseBSPFile +============= +*/ +void CloseBSPFile ( void ) +{ + free (header); +} + +/* +============= +LoadBSPFile +============= +*/ +void LoadBSPFile (char *filename) +{ + OpenBSPFile( filename ); + + nummodels = CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t)); + numvertexes = CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t)); + numplanes = CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t)); + numleafs = LoadLeafs(); + numnodes = CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t)); + CopyLump (LUMP_TEXINFO, texinfo); + numtexdata = CopyLump (LUMP_TEXDATA, dtexdata, sizeof(dtexdata_t)); + + CopyLump( LUMP_DISPINFO, g_dispinfo ); + CopyLump( LUMP_DISP_VERTS, g_DispVerts ); + CopyLump( LUMP_DISP_TRIS, g_DispTris ); + CopyLump( LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS, g_DispLightmapSamplePositions ); + CopyLump( LUMP_FACE_MACRO_TEXTURE_INFO, g_FaceMacroTextureInfos ); + + numfaces = CopyLump (LUMP_FACES, dfaces, sizeof(dface_t), LUMP_FACES_VERSION); + if (HasLump( LUMP_FACES_HDR )) + numfaces_hdr = CopyLump (LUMP_FACES_HDR, dfaces_hdr, sizeof(dface_t), LUMP_FACES_VERSION); + else + numfaces_hdr = 0; + + g_numprimitives = CopyLump (LUMP_PRIMITIVES, g_primitives, sizeof( dprimitive_t ) ); + g_numprimverts = CopyLump (LUMP_PRIMVERTS, g_primverts, sizeof( dprimvert_t ) ); + g_numprimindices = CopyLump (LUMP_PRIMINDICES, g_primindices, sizeof( unsigned short ) ); + numorigfaces = CopyLump( LUMP_ORIGINALFACES, dorigfaces, sizeof( dface_t ) ); // original faces + numleaffaces = CopyLump (LUMP_LEAFFACES, dleaffaces, sizeof(dleaffaces[0])); + numleafbrushes = CopyLump (LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0])); + numsurfedges = CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0])); + numedges = CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t)); + numbrushes = CopyLump (LUMP_BRUSHES, dbrushes, sizeof(dbrush_t)); + numbrushsides = CopyLump (LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t)); + numareas = CopyLump (LUMP_AREAS, dareas, sizeof(darea_t)); + numareaportals = CopyLump (LUMP_AREAPORTALS, dareaportals, sizeof(dareaportal_t)); + + visdatasize = CopyLump (LUMP_VISIBILITY, dvisdata, 1); + CopyOptionalLump(LUMP_LIGHTING, dlightdataLDR, LUMP_LIGHTING_VERSION ); + CopyOptionalLump(LUMP_LIGHTING_HDR, dlightdataHDR, LUMP_LIGHTING_VERSION ); + + CopyOptionalLump(LUMP_LEAF_AMBIENT_LIGHTING, g_LeafAmbientLightingLDR ); + CopyOptionalLump(LUMP_LEAF_AMBIENT_LIGHTING_HDR, g_LeafAmbientLightingHDR ); + + CopyLump (LUMP_ENTITIES, dentdata); + numworldlightsLDR = CopyLump (LUMP_WORLDLIGHTS, dworldlightsLDR, sizeof(dworldlight_t) ); + numworldlightsHDR = CopyLump (LUMP_WORLDLIGHTS_HDR, dworldlightsHDR, sizeof(dworldlight_t) ); + + // not present on pc, not an error + CopyOptionalLump( LUMP_LIGHTMAPPAGES, g_dLightmapPages, LUMP_LIGHTMAPPAGES_VERSION ); + CopyOptionalLump( LUMP_LIGHTMAPPAGEINFOS, g_dLightmapPageInfos, LUMP_LIGHTMAPPAGEINFOS_VERSION ); + + numportals = CopyLump (LUMP_PORTALS, dportals, sizeof(dportal_t)); + numclusters = CopyLump (LUMP_CLUSTERS, dclusters, sizeof(dcluster_t)); + numleafwaterdata = CopyLump( LUMP_LEAFWATERDATA, dleafwaterdata, sizeof( dleafwaterdata_t ) ); + numportalverts = CopyLump (LUMP_PORTALVERTS, dportalverts, sizeof(unsigned short)); + numclusterportals = CopyLump (LUMP_CLUSTERPORTALS, dclusterportals, sizeof(unsigned short)); + g_PhysCollideSize = CopyVariableLump( LUMP_PHYSCOLLIDE, (void**)&g_pPhysCollide, 1 ); + + g_numvertnormals = CopyLump (LUMP_VERTNORMALS, g_vertnormals, sizeof( g_vertnormals[0] )); + g_numvertnormalindices = CopyLump (LUMP_VERTNORMALINDICES, g_vertnormalindices, sizeof( g_vertnormalindices[0] )); + + g_nClipPortalVerts = CopyLump( LUMP_CLIPPORTALVERTS, g_ClipPortalVerts, sizeof( g_ClipPortalVerts[0] ) ); + g_nCubemapSamples = CopyLump( LUMP_CUBEMAPS, g_CubemapSamples, sizeof( g_CubemapSamples[0] ) ); + + CopyLump( LUMP_TEXDATA_STRING_DATA, g_TexDataStringData ); + CopyLump( LUMP_TEXDATA_STRING_TABLE, g_TexDataStringTable ); + + g_nOverlayCount = CopyLump( LUMP_OVERLAYS, g_Overlays, sizeof( g_Overlays[0] ) ); + g_nWaterOverlayCount = CopyLump( LUMP_WATEROVERLAYS, g_WaterOverlays, sizeof( g_WaterOverlays[0] ) ); + + dflagslump_t flags_lump; + + if (HasLump( LUMP_MAP_FLAGS )) + CopyLump ( LUMP_MAP_FLAGS, &flags_lump, sizeof( flags_lump ) ); + else + memset(&flags_lump, 0, sizeof( flags_lump ) ); // default flags to 0 + + g_LevelFlags = flags_lump.m_LevelFlags; + + LoadOcclusionLump(); + + CopyLump( LUMP_LEAFMINDISTTOWATER, g_LeafMinDistToWater, sizeof( g_LeafMinDistToWater[0] ) ); + + /* + int crap; + for( crap = 0; crap < g_nBSPStringTable; crap++ ) + { + Msg( "stringtable %d", ( int )crap ); + Msg( " %d:", ( int )g_BSPStringTable[crap] ); + puts( &g_BSPStringData[g_BSPStringTable[crap]] ); + puts( "\n" ); + } + */ + + // Load PAK file lump into appropriate data structure + { + byte *pakbuffer = NULL; + int paksize = CopyVariableLump( LUMP_PAKFILE, ( void ** )&pakbuffer, 1 ); + if ( paksize > 0 ) + { + GetPakFile()->ParseFromBuffer( pakbuffer, paksize ); + } + else + { + GetPakFile()->Reset(); + } + + free( pakbuffer ); + } + + ParseGameLump( header ); + + // NOTE: Do NOT call CopyLump after Lumps_Parse() it parses all un-Copyied lumps + Lumps_Parse(); // parse any additional lumps + + CloseBSPFile(); // everything has been copied out +} + + +/* +============= +LoadBSPFileFilesystemOnly +============= +*/ +void LoadBSPFile_FileSystemOnly (char *filename) +{ + int i; + + Lumps_Init(); +// +// load the file header +// + LoadFile (filename, (void **)&header); + +// swap the header + for (i=0 ; i< sizeof(dheader_t)/4 ; i++) + ((int *)header)[i] = LittleLong ( ((int *)header)[i]); + + if (header->ident != IDBSPHEADER) + Error ("%s is not a IBSP file", filename); + if (header->version < MINBSPVERSION || header->version > BSPVERSION) + Error ("%s is version %i, not %i", filename, header->version, BSPVERSION); + + // Load PAK file lump into appropriate data structure + { + byte *pakbuffer = NULL; + int paksize = CopyVariableLump( LUMP_PAKFILE, ( void ** )&pakbuffer, 1 ); + if ( paksize > 0 ) + { + GetPakFile()->ParseFromBuffer( pakbuffer, paksize ); + } + else + { + GetPakFile()->Reset(); + } + + free( pakbuffer ); + } + + free (header); // everything has been copied out +} + +void ExtractZipFileFromBSP( char *pBSPFileName, char *pZipFileName ) +{ + Lumps_Init(); +// +// load the file header +// + LoadFile ( pBSPFileName, (void **)&header); + +// swap the header + int i; + for (i=0 ; i< sizeof(dheader_t)/4 ; i++) + ((int *)header)[i] = LittleLong ( ((int *)header)[i]); + + if (header->ident != IDBSPHEADER) + Error ("%s is not a IBSP file", pBSPFileName); + if (header->version < MINBSPVERSION || BSPVERSION > BSPVERSION) + Error ("%s is version %i, not %i", pBSPFileName, header->version, BSPVERSION); + + byte *pakbuffer = NULL; + int paksize = CopyVariableLump( LUMP_PAKFILE, ( void ** )&pakbuffer, 1 ); + if ( paksize > 0 ) + { + byte *pakbuffer = NULL; + int paksize = CopyVariableLump( LUMP_PAKFILE, ( void ** )&pakbuffer, 1 ); + + FILE *fp; + fp = fopen( pZipFileName, "wb" ); + if( !fp ) + { + fprintf( stderr, "can't open %s\n", pZipFileName ); + return; + } + + fwrite( pakbuffer, paksize, 1, fp ); + fclose( fp ); + } + else + { + int paksize = CopyVariableLump( LUMP_XZIPPAKFILE, ( void ** )&pakbuffer, 1 ); + if ( paksize > 0 ) + { + byte *pakbuffer = NULL; + int paksize = CopyVariableLump( LUMP_XZIPPAKFILE, ( void ** )&pakbuffer, 1 ); + + FILE *fp; + fp = fopen( pZipFileName, "wb" ); + if( !fp ) + { + fprintf( stderr, "can't open %s\n", pZipFileName ); + return; + } + + fwrite( pakbuffer, paksize, 1, fp ); + fclose( fp ); + } + else + { + fprintf( stderr, "zip file is zero length!\n" ); + } + } +} + +/* +============= +LoadBSPFileTexinfo + +Only loads the texinfo lump, so qdata can scan for textures +============= +*/ +void LoadBSPFileTexinfo (char *filename) +{ + int i; + FILE *f; + int length, ofs; + + header = (dheader_t*)malloc(sizeof(dheader_t)); + + f = fopen (filename, "rb"); + fread (header, sizeof(dheader_t), 1, f); + +// swap the header + for (i=0 ; i< sizeof(dheader_t)/4 ; i++) + ((int *)header)[i] = LittleLong ( ((int *)header)[i]); + + if (header->ident != IDBSPHEADER) + { + Error ("%s is not a IBSP file", filename); + } + if (header->version < MINBSPVERSION || header->version > BSPVERSION) + { + Error ("%s is version %i, not %i", filename, header->version, BSPVERSION); + } + + length = header->lumps[LUMP_TEXINFO].filelen; + ofs = header->lumps[LUMP_TEXINFO].fileofs; + + int nCount = length / sizeof(texinfo_t); + + texinfo.Purge(); + texinfo.AddMultipleToTail( nCount ); + + fseek (f, ofs, SEEK_SET); + fread (texinfo.Base(), length, 1, f); + fclose (f); + + free (header); // everything has been copied out + +} + + +//============================================================================ + +static void AddLump (int lumpnum, void *data, int len, int version ) +{ + lump_t *lump; + + g_Lumps.size[lumpnum] = 0; // mark it written + + lump = &header->lumps[lumpnum]; + + lump->fileofs = LittleLong( g_pFileSystem->Tell(wadfile) ); + lump->filelen = LittleLong(len); + lump->version= LittleLong( version ); + lump->fourCC[0] = ( char )0; + lump->fourCC[1] = ( char )0; + lump->fourCC[2] = ( char )0; + lump->fourCC[3] = ( char )0; + SafeWrite (wadfile, data, (len+3)&~3); +} + +template< class T > +static void AddLump( int lumpnum, CUtlVector &data, int version = 0 ) +{ + AddLump( lumpnum, data.Base(), data.Count() * sizeof(T), version ); +} + + +/* +============= +WriteBSPFile + +Swaps the bsp file in place, so it should not be referenced again +============= +*/ +void WriteBSPFile (char *filename, char* xzpLumpFilename ) +{ + if ( texinfo.Count() > MAX_MAP_TEXINFO ) + { + Error( "Map has too many texinfos (has %d, can have at most %d)\n", texinfo.Count(), MAX_MAP_TEXINFO ); + return; + } + + header = &outheader; + memset (header, 0, sizeof(dheader_t)); + + header->ident = LittleLong (IDBSPHEADER); + header->version = LittleLong (BSPVERSION); + header->mapRevision = LittleLong( g_MapRevision ); + + wadfile = SafeOpenWrite (filename); + SafeWrite (wadfile, header, sizeof(dheader_t)); // overwritten later + + AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t)); + AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t), LUMP_LEAFS_VERSION); + // Make ambient lighting of zero so that the rest of the code can assume that this lump is here. + if ( !g_bHDR && g_LeafAmbientLightingLDR.Count() == 0 ) + { + g_LeafAmbientLightingLDR.SetCount( numleafs ); + memset( g_LeafAmbientLightingLDR.Base(), 0, g_LeafAmbientLightingLDR.Count()*sizeof(CompressedLightCube )); + } + AddLump (LUMP_LEAF_AMBIENT_LIGHTING, g_LeafAmbientLightingLDR, g_LeafAmbientLightingLDR.Count()*sizeof(CompressedLightCube)); + // Make ambient lighting of zero so that the rest of the code can assume that this lump is here. + if ( g_bHDR && g_LeafAmbientLightingHDR.Count() == 0 ) + { + g_LeafAmbientLightingHDR.SetCount( numleafs ); + memset( g_LeafAmbientLightingHDR.Base(), 0, g_LeafAmbientLightingHDR.Count()*sizeof(CompressedLightCube )); + } + AddLump (LUMP_LEAF_AMBIENT_LIGHTING_HDR, g_LeafAmbientLightingHDR, g_LeafAmbientLightingHDR.Count()*sizeof(CompressedLightCube)); + + AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t)); + AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t)); + AddLump (LUMP_TEXINFO, texinfo); + AddLump (LUMP_TEXDATA, dtexdata, numtexdata*sizeof(dtexdata_t)); + + AddLump (LUMP_DISPINFO, g_dispinfo ); + AddLump (LUMP_DISP_VERTS, g_DispVerts ); + AddLump (LUMP_DISP_TRIS, g_DispTris ); + AddLump (LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS, g_DispLightmapSamplePositions ); + AddLump (LUMP_FACE_MACRO_TEXTURE_INFO, g_FaceMacroTextureInfos ); + + AddLump (LUMP_PRIMITIVES, g_primitives, g_numprimitives * sizeof( dprimitive_t ) ); + AddLump (LUMP_PRIMVERTS, g_primverts, g_numprimverts * sizeof( dprimvert_t ) ); + AddLump (LUMP_PRIMINDICES, g_primindices, g_numprimindices * sizeof( unsigned short ) ); + AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t), LUMP_FACES_VERSION); + if (numfaces_hdr) + AddLump (LUMP_FACES_HDR, dfaces_hdr, numfaces_hdr*sizeof(dface_t), LUMP_FACES_VERSION); + + AddLump (LUMP_ORIGINALFACES, dorigfaces, numorigfaces*sizeof( dface_t ) ); // original faces lump + AddLump (LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t)); + AddLump (LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t)); + AddLump (LUMP_LEAFFACES, dleaffaces, numleaffaces*sizeof(dleaffaces[0])); + AddLump (LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0])); + AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0])); + AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t)); + AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t)); + AddLump (LUMP_AREAS, dareas, numareas*sizeof(darea_t)); + AddLump (LUMP_AREAPORTALS, dareaportals, numareaportals*sizeof(dareaportal_t)); + + AddLump (LUMP_LIGHTING, dlightdataLDR, LUMP_LIGHTING_VERSION); + AddLump (LUMP_LIGHTING_HDR, dlightdataHDR, LUMP_LIGHTING_VERSION); + AddLump (LUMP_VISIBILITY, dvisdata, visdatasize); + AddLump (LUMP_ENTITIES, dentdata); + AddLump (LUMP_WORLDLIGHTS, dworldlightsLDR, numworldlightsLDR*sizeof(dworldlight_t)); + AddLump (LUMP_WORLDLIGHTS_HDR, dworldlightsHDR, numworldlightsHDR*sizeof(dworldlight_t)); + AddLump (LUMP_LEAFWATERDATA, dleafwaterdata, numleafwaterdata*sizeof(dleafwaterdata_t)); + + AddOcclusionLump(); + + dflagslump_t flags_lump; + + flags_lump.m_LevelFlags = g_LevelFlags; + AddLump( LUMP_MAP_FLAGS, &flags_lump, sizeof( flags_lump) ); + + // NOTE: This is just for debugging, so it is disabled in release maps +#if 0 + // add the vis portals to the BSP for visualization + AddLump (LUMP_PORTALS, dportals, numportals*sizeof(dportal_t)); + AddLump (LUMP_CLUSTERS, dclusters, numclusters*sizeof(dcluster_t)); + AddLump (LUMP_PORTALVERTS, dportalverts, numportalverts*sizeof(unsigned short)); + AddLump (LUMP_CLUSTERPORTALS, dclusterportals, numclusterportals*sizeof(unsigned short)); +#endif + + AddLump (LUMP_CLIPPORTALVERTS, g_ClipPortalVerts, g_nClipPortalVerts*sizeof(g_ClipPortalVerts[0])); + AddLump (LUMP_CUBEMAPS, g_CubemapSamples, g_nCubemapSamples * sizeof( g_CubemapSamples[0] ) ); + AddLump (LUMP_TEXDATA_STRING_DATA, g_TexDataStringData ); + AddLump (LUMP_TEXDATA_STRING_TABLE, g_TexDataStringTable ); + AddLump (LUMP_OVERLAYS, g_Overlays, g_nOverlayCount * sizeof( g_Overlays[0] ) ); + AddLump (LUMP_WATEROVERLAYS, g_WaterOverlays, g_nWaterOverlayCount * sizeof( g_WaterOverlays[0] ) ); + + if ( g_pPhysCollide ) + { + AddLump (LUMP_PHYSCOLLIDE, g_pPhysCollide, g_PhysCollideSize); + } + + AddLump (LUMP_VERTNORMALS, g_vertnormals, g_numvertnormals * sizeof( g_vertnormals[0] ) ); + AddLump (LUMP_VERTNORMALINDICES, g_vertnormalindices, g_numvertnormalindices * sizeof( g_vertnormalindices[0] ) ); + + AddLump (LUMP_LEAFMINDISTTOWATER, g_LeafMinDistToWater, numleafs * sizeof( g_LeafMinDistToWater[0] ) ); + + AddLump (LUMP_LIGHTMAPPAGES, g_dLightmapPages, LUMP_LIGHTMAPPAGES_VERSION); + AddLump (LUMP_LIGHTMAPPAGEINFOS, g_dLightmapPageInfos, LUMP_LIGHTMAPPAGEINFOS_VERSION); + + AddGameLumps(); + + /* + { + GetPakFile()->AddFileToPack( "cfg/config.cfg", "d:\\tf2\\tf2\\cfg\\config.cfg" ); + } + */ + + // Write pakfile lump to disk + if( xzpLumpFilename ) + { + WriteXZPPakFileLump( xzpLumpFilename ); + } + else + { + WritePakFileLump(); + } + + // NOTE: Do NOT call AddLump after Lumps_Write() it writes all un-Added lumps + Lumps_Write(); // write any additional lumps + + g_pFileSystem->Seek (wadfile, 0, FILESYSTEM_SEEK_HEAD); + SafeWrite (wadfile, header, sizeof(dheader_t)); + g_pFileSystem->Close (wadfile); +} + +// Generate the next clear lump filename for the bsp file +bool GenerateNextLumpFileName( const char *bspfilename, char *lumpfilename, int buffsize ) +{ + for (int i = 0; i < MAX_LUMPFILES; i++) + { + GenerateLumpFileName( bspfilename, lumpfilename, buffsize, i ); + + if ( !g_pFileSystem->FileExists( lumpfilename ) ) + return true; + } + + return false; +} + +void WriteLumpToFile( char *filename, int lump ) +{ + if ( !HasLump(lump) ) + return; + + char lumppre[MAX_PATH]; + if ( !GenerateNextLumpFileName( filename, lumppre, MAX_PATH ) ) + { + Warning( "Failed to find valid lump filename for bsp %s.\n", filename ); + return; + } + + // Open the file + FileHandle_t lumpfile = g_pFileSystem->Open(lumppre, "wb"); + if ( !lumpfile ) + { + Error ("Error opening %s! (Check for write enable)\n",filename); + return; + } + + int ofs = header->lumps[lump].fileofs; + int length = header->lumps[lump].filelen; + + // Write the header + lumpfileheader_t lumpHeader; + lumpHeader.lumpID = lump; + lumpHeader.lumpVersion = LumpVersion(lump); + lumpHeader.lumpLength = length; + lumpHeader.mapRevision = LittleLong( g_MapRevision ); + lumpHeader.lumpOffset = sizeof(lumpfileheader_t); // Lump starts after the header + SafeWrite (lumpfile, &lumpHeader, sizeof(lumpfileheader_t)); + + // Write the lump + SafeWrite (lumpfile, (byte *)header + ofs, length); +} + +//============================================================================ +#define ENTRIES(a) (sizeof(a)/sizeof(*(a))) +#define ENTRYSIZE(a) (sizeof(*(a))) + +int ArrayUsage( char *szItem, int items, int maxitems, int itemsize ) +{ + float percentage = maxitems ? items * 100.0 / maxitems : 0.0; + + Msg("%-17.17s %8i/%-8i %8i/%-8i (%4.1f%%) ", + szItem, items, maxitems, items * itemsize, maxitems * itemsize, percentage ); + if ( percentage > 80.0 ) + Msg( "VERY FULL!\n" ); + else if ( percentage > 95.0 ) + Msg( "SIZE DANGER!\n" ); + else if ( percentage > 99.9 ) + Msg( "SIZE OVERFLOW!!!\n" ); + else + Msg( "\n" ); + return items * itemsize; +} + +int GlobUsage( char *szItem, int itemstorage, int maxstorage ) +{ + float percentage = maxstorage ? itemstorage * 100.0 / maxstorage : 0.0; + Msg("%-17.17s [variable] %8i/%-8i (%4.1f%%) ", + szItem, itemstorage, maxstorage, percentage ); + if ( percentage > 80.0 ) + Msg( "VERY FULL!\n" ); + else if ( percentage > 95.0 ) + Msg( "SIZE DANGER!\n" ); + else if ( percentage > 99.9 ) + Msg( "SIZE OVERFLOW!!!\n" ); + else + Msg( "\n" ); + return itemstorage; +} + +/* +============= +PrintBSPFileSizes + +Dumps info about current file +============= +*/ +void PrintBSPFileSizes (void) +{ + int totalmemory = 0; + +// if (!num_entities) +// ParseEntities (); + + Msg("\n"); + Msg( "%-17s %16s %16s %9s \n", "Object names", "Objects/Maxobjs", "Memory / Maxmem", "Fullness" ); + Msg( "%-17s %16s %16s %9s \n", "------------", "---------------", "---------------", "--------" ); + + totalmemory += ArrayUsage( "models", nummodels, ENTRIES(dmodels), ENTRYSIZE(dmodels) ); + totalmemory += ArrayUsage( "brushes", numbrushes, ENTRIES(dbrushes), ENTRYSIZE(dbrushes) ); + totalmemory += ArrayUsage( "brushsides", numbrushsides, ENTRIES(dbrushsides), ENTRYSIZE(dbrushsides) ); + totalmemory += ArrayUsage( "planes", numplanes, ENTRIES(dplanes), ENTRYSIZE(dplanes) ); + totalmemory += ArrayUsage( "vertexes", numvertexes, ENTRIES(dvertexes), ENTRYSIZE(dvertexes) ); + totalmemory += ArrayUsage( "nodes", numnodes, ENTRIES(dnodes), ENTRYSIZE(dnodes) ); + totalmemory += ArrayUsage( "texinfos", texinfo.Count(),MAX_MAP_TEXINFO, sizeof(texinfo_t) ); + totalmemory += ArrayUsage( "texdata", numtexdata, ENTRIES(dtexdata), ENTRYSIZE(dtexdata) ); + + totalmemory += ArrayUsage( "dispinfos", g_dispinfo.Count(), 0, sizeof( ddispinfo_t ) ); + totalmemory += ArrayUsage( "disp_verts", g_DispVerts.Count(), 0, sizeof( g_DispVerts[0] ) ); + totalmemory += ArrayUsage( "disp_tris", g_DispTris.Count(), 0, sizeof( g_DispTris[0] ) ); + totalmemory += ArrayUsage( "disp_lmsamples",g_DispLightmapSamplePositions.Count(),0,sizeof( g_DispLightmapSamplePositions[0] ) ); + + totalmemory += ArrayUsage( "faces", numfaces, ENTRIES(dfaces), ENTRYSIZE(dfaces) ); + totalmemory += ArrayUsage( "hdr faces", numfaces_hdr, ENTRIES(dfaces_hdr), ENTRYSIZE(dfaces_hdr) ); + totalmemory += ArrayUsage( "origfaces", numorigfaces, ENTRIES(dorigfaces), ENTRYSIZE(dorigfaces) ); // original faces + totalmemory += ArrayUsage( "leaves", numleafs, ENTRIES(dleafs), ENTRYSIZE(dleafs) ); + totalmemory += ArrayUsage( "leaffaces", numleaffaces, ENTRIES(dleaffaces), ENTRYSIZE(dleaffaces) ); + totalmemory += ArrayUsage( "leafbrushes", numleafbrushes, ENTRIES(dleafbrushes), ENTRYSIZE(dleafbrushes) ); + totalmemory += ArrayUsage( "areas", numareas, ENTRIES(dareas), ENTRYSIZE(dareas) ); + totalmemory += ArrayUsage( "surfedges", numsurfedges, ENTRIES(dsurfedges), ENTRYSIZE(dsurfedges) ); + totalmemory += ArrayUsage( "edges", numedges, ENTRIES(dedges), ENTRYSIZE(dedges) ); + totalmemory += ArrayUsage( "LDR worldlights", numworldlightsLDR, ENTRIES(dworldlightsLDR), ENTRYSIZE(dworldlightsLDR) ); + totalmemory += ArrayUsage( "HDR worldlights", numworldlightsHDR, ENTRIES(dworldlightsHDR), ENTRYSIZE(dworldlightsHDR) ); + totalmemory += ArrayUsage( "waterstrips", g_numprimitives,ENTRIES(g_primitives), ENTRYSIZE(g_primitives) ); + totalmemory += ArrayUsage( "waterverts", g_numprimverts, ENTRIES(g_primverts), ENTRYSIZE(g_primverts) ); + totalmemory += ArrayUsage( "waterindices", g_numprimindices,ENTRIES(g_primindices),ENTRYSIZE(g_primindices) ); + totalmemory += ArrayUsage( "cubemapsamples", g_nCubemapSamples,ENTRIES(g_CubemapSamples),ENTRYSIZE(g_CubemapSamples) ); + totalmemory += ArrayUsage( "overlays", g_nOverlayCount, ENTRIES(g_Overlays), ENTRYSIZE(g_Overlays) ); + + totalmemory += GlobUsage( "LDR lightdata", dlightdataLDR.Count(), 0 ); + totalmemory += GlobUsage( "HDR lightdata", dlightdataHDR.Count(), 0 ); + totalmemory += GlobUsage( "visdata", visdatasize, sizeof(dvisdata) ); + totalmemory += GlobUsage( "entdata", dentdata.Count(), 384*1024 ); // goal is <384K + + totalmemory += ArrayUsage( "LDR leaf ambient lighting", g_LeafAmbientLightingLDR.Count(), MAX_MAP_LEAFS, sizeof( g_LeafAmbientLightingLDR[0] ) ); + totalmemory += ArrayUsage( "HDR leaf ambient lighting", g_LeafAmbientLightingHDR.Count(), MAX_MAP_LEAFS, sizeof( g_LeafAmbientLightingHDR[0] ) ); + + totalmemory += ArrayUsage( "occluders", g_OccluderData.Count(), 0, sizeof( g_OccluderData[0] ) ); + totalmemory += ArrayUsage( "occluder polygons", g_OccluderPolyData.Count(), 0, sizeof( g_OccluderPolyData[0] ) ); + totalmemory += ArrayUsage( "occluder vert ind",g_OccluderVertexIndices.Count(),0, sizeof( g_OccluderVertexIndices[0] ) ); + + GameLumpHandle_t h = GetGameLumpHandle( GAMELUMP_DETAIL_PROPS ); + if (h != InvalidGameLump()) + totalmemory += GlobUsage( "detail props", 1, GameLumpSize(h) ); + h = GetGameLumpHandle( GAMELUMP_DETAIL_PROP_LIGHTING ); + if (h != InvalidGameLump()) + totalmemory += GlobUsage( "dtl prp lght", 1, GameLumpSize(h) ); + h = GetGameLumpHandle( GAMELUMP_DETAIL_PROP_LIGHTING_HDR ); + if (h != InvalidGameLump()) + totalmemory += GlobUsage( "HDR dtl prp lght", 1, GameLumpSize(h) ); + h = GetGameLumpHandle( GAMELUMP_STATIC_PROPS ); + if (h != InvalidGameLump()) + totalmemory += GlobUsage( "static props", 1, GameLumpSize(h) ); + + totalmemory += GlobUsage( "pakfile", GetPakFile()->EstimateSize(), 0 ); + + Msg( "\nLevel flags = %x\n", g_LevelFlags ); + + Msg( "\nWin32 Specific Data:\n" ); + + int totalWin32Specificmemory = 0; + // HACKHACK: Set physics limit at 4MB, in reality this is totally dynamic + totalWin32Specificmemory += GlobUsage( "physics", g_PhysCollideSize, 4*1024*1024 ); + Msg( "==== Total Win32 BSP file data space used: %d bytes ====\n", totalmemory + totalWin32Specificmemory ); + +#ifdef _XBOX + Msg( "\nXBox Specific Data:\n" ); + int totalXBoxSpecificmemory = 0; + totalXBoxSpecificmemory += GlobUsage( "lightmap pages", g_dLightmapPages.Count()*sizeof(dlightmappage_t), 0 ); + totalXBoxSpecificmemory += GlobUsage( "lightmap infos", g_dLightmapPageInfos.Count()*sizeof(dlightmappageinfo_t), 0 ); + Msg( "==== Total XBox BSP file data space used: %d bytes ====\n", totalmemory + totalXBoxSpecificmemory ); +#endif // _XBOX + + Msg( "\n" ); + + int triangleCount = 0; + + for ( int i = 0; i < numfaces; i++ ) + { + // face tris = numedges - 2 + triangleCount += dfaces[i].numedges - 2; + } + Msg("Total triangle count: %d\n", triangleCount ); + + // UNDONE: + // areaportals, portals, texdata, clusters, worldlights, portalverts +} + +/* +============= +PrintBSPPackDirectory + +Dumps a list of files stored in the bsp pack. +============= +*/ +void PrintBSPPackDirectory( void ) +{ + GetPakFile()->PrintDirectory(); +} + + +//============================================ + +int num_entities; +entity_t entities[MAX_MAP_ENTITIES]; + +void StripTrailing (char *e) +{ + char *s; + + s = e + strlen(e)-1; + while (s >= e && *s <= 32) + { + *s = 0; + s--; + } +} + +/* +================= +ParseEpair +================= +*/ +epair_t *ParseEpair (void) +{ + epair_t *e; + + e = (epair_t*)malloc (sizeof(epair_t)); + memset (e, 0, sizeof(epair_t)); + + if (strlen(token) >= MAX_KEY-1) + Error ("ParseEpar: token too long"); + e->key = copystring(token); + GetToken (false); + if (strlen(token) >= MAX_VALUE-1) + Error ("ParseEpar: token too long"); + e->value = copystring(token); + + // strip trailing spaces + StripTrailing (e->key); + StripTrailing (e->value); + + return e; +} + + +/* +================ +ParseEntity +================ +*/ +qboolean ParseEntity (void) +{ + epair_t *e; + entity_t *mapent; + + if (!GetToken (true)) + return false; + + if (strcmp (token, "{") ) + Error ("ParseEntity: { not found"); + + if (num_entities == MAX_MAP_ENTITIES) + Error ("num_entities == MAX_MAP_ENTITIES"); + + mapent = &entities[num_entities]; + num_entities++; + + do + { + if (!GetToken (true)) + Error ("ParseEntity: EOF without closing brace"); + if (!strcmp (token, "}") ) + break; + e = ParseEpair (); + e->next = mapent->epairs; + mapent->epairs = e; + } while (1); + + return true; +} + +/* +================ +ParseEntities + +Parses the dentdata string into entities +================ +*/ +void ParseEntities (void) +{ + num_entities = 0; + ParseFromMemory (dentdata.Base(), dentdata.Count()); + + while (ParseEntity ()) + { + } +} + + +/* +================ +UnparseEntities + +Generates the dentdata string from all the entities +================ +*/ +void UnparseEntities (void) +{ + epair_t *ep; + char line[2048]; + int i; + char key[1024], value[1024]; + + CUtlBuffer buffer(0,0,true); + buffer.EnsureCapacity( 256 * 1024 ); + + for (i=0 ; inext) + { + strcpy (key, ep->key); + StripTrailing (key); + strcpy (value, ep->value); + StripTrailing (value); + + sprintf(line, "\"%s\" \"%s\"\n", key, value); + buffer.PutString( line ); + } + buffer.PutString("}\n"); + } + int entdatasize = buffer.TellPut()+1; + + dentdata.SetSize( entdatasize ); + memcpy( dentdata.Base(), buffer.Base(), entdatasize-1 ); + dentdata[entdatasize-1] = 0; +} + +void PrintEntity (entity_t *ent) +{ + epair_t *ep; + + Msg ("------- entity %p -------\n", ent); + for (ep=ent->epairs ; ep ; ep=ep->next) + { + Msg ("%s = %s\n", ep->key, ep->value); + } + +} + +void SetKeyValue(entity_t *ent, const char *key, const char *value) +{ + epair_t *ep; + + for (ep=ent->epairs ; ep ; ep=ep->next) + if (!strcmp (ep->key, key) ) + { + free (ep->value); + ep->value = copystring(value); + return; + } + ep = (epair_t*)malloc (sizeof(*ep)); + ep->next = ent->epairs; + ent->epairs = ep; + ep->key = copystring(key); + ep->value = copystring(value); +} + +char *ValueForKey (entity_t *ent, char *key) +{ + epair_t *ep; + + for (ep=ent->epairs ; ep ; ep=ep->next) + if (!strcmp (ep->key, key) ) + return ep->value; + return ""; +} + +vec_t FloatForKey (entity_t *ent, char *key) +{ + char *k; + + k = ValueForKey (ent, key); + return atof(k); +} + +int IntForKey (entity_t *ent, char *key) +{ + char *k; + + k = ValueForKey (ent, key); + return atol(k); +} + +void GetVectorForKey (entity_t *ent, char *key, Vector& vec) +{ + char *k; + double v1, v2, v3; + + k = ValueForKey (ent, key); +// scanf into doubles, then assign, so it is vec_t size independent + v1 = v2 = v3 = 0; + sscanf (k, "%lf %lf %lf", &v1, &v2, &v3); + vec[0] = v1; + vec[1] = v2; + vec[2] = v3; +} + +void GetVector2DForKey (entity_t *ent, char *key, Vector2D& vec) +{ + char *k; + double v1, v2; + + k = ValueForKey (ent, key); +// scanf into doubles, then assign, so it is vec_t size independent + v1 = v2 = 0; + sscanf (k, "%lf %lf", &v1, &v2); + vec[0] = v1; + vec[1] = v2; +} + +void GetAnglesForKey (entity_t *ent, char *key, QAngle& angle) +{ + char *k; + double v1, v2, v3; + + k = ValueForKey (ent, key); +// scanf into doubles, then assign, so it is vec_t size independent + v1 = v2 = v3 = 0; + sscanf (k, "%lf %lf %lf", &v1, &v2, &v3); + angle[0] = v1; + angle[1] = v2; + angle[2] = v3; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void BuildFaceCalcWindingData( dface_t *pFace, int *points ) +{ + for( int i = 0; i < pFace->numedges; i++ ) + { + int eIndex = dsurfedges[pFace->firstedge+i]; + if( eIndex < 0 ) + { + points[i] = dedges[-eIndex].v[1]; + } + else + { + points[i] = dedges[eIndex].v[0]; + } + } +} + + +void TriStripToTriList( + unsigned short const *pTriStripIndices, + int nTriStripIndices, + unsigned short **pTriListIndices, + int *pnTriListIndices ) +{ + int nMaxTriListIndices = (nTriStripIndices - 2) * 3; + *pTriListIndices = new unsigned short[ nMaxTriListIndices ]; + *pnTriListIndices = 0; + + for( int i=0; i < nTriStripIndices - 2; i++ ) + { + if( pTriStripIndices[i] == pTriStripIndices[i+1] || + pTriStripIndices[i] == pTriStripIndices[i+2] || + pTriStripIndices[i+1] == pTriStripIndices[i+2] ) + { + } + else + { + // Flip odd numbered tris.. + if( i & 1 ) + { + (*pTriListIndices)[(*pnTriListIndices)++] = pTriStripIndices[i+2]; + (*pTriListIndices)[(*pnTriListIndices)++] = pTriStripIndices[i+1]; + (*pTriListIndices)[(*pnTriListIndices)++] = pTriStripIndices[i]; + } + else + { + (*pTriListIndices)[(*pnTriListIndices)++] = pTriStripIndices[i]; + (*pTriListIndices)[(*pnTriListIndices)++] = pTriStripIndices[i+1]; + (*pTriListIndices)[(*pnTriListIndices)++] = pTriStripIndices[i+2]; + } + } + } +} + + +void CalcTextureCoordsAtPoints( + float const texelsPerWorldUnits[2][4], + int const subtractOffset[2], + Vector const *pPoints, + int const nPoints, + Vector2D *pCoords ) +{ + for( int i=0; i < nPoints; i++ ) + { + for( int iCoord=0; iCoord < 2; iCoord++ ) + { + float *pDestCoord = &pCoords[i][iCoord]; + + *pDestCoord = 0; + for( int iDot=0; iDot < 3; iDot++ ) + *pDestCoord += pPoints[i][iDot] * texelsPerWorldUnits[iCoord][iDot]; + + *pDestCoord += texelsPerWorldUnits[iCoord][3]; + *pDestCoord -= subtractOffset[iCoord]; + } + } +} + + +/* +================ +CalcFaceExtents + +Fills in s->texmins[] and s->texsize[] +================ +*/ +void CalcFaceExtents(dface_t *s, int lightmapTextureMinsInLuxels[2], int lightmapTextureSizeInLuxels[2]) +{ + vec_t mins[2], maxs[2], val=0; + int i,j, e=0; + dvertex_t *v=NULL; + texinfo_t *tex=NULL; + + mins[0] = mins[1] = 1e24; + maxs[0] = maxs[1] = -1e24; + + tex = &texinfo[s->texinfo]; + + for (i=0 ; inumedges ; i++) + { + e = dsurfedges[s->firstedge+i]; + if (e >= 0) + v = dvertexes + dedges[e].v[0]; + else + v = dvertexes + dedges[-e].v[1]; + + for (j=0 ; j<2 ; j++) + { + val = v->point[0] * tex->lightmapVecsLuxelsPerWorldUnits[j][0] + + v->point[1] * tex->lightmapVecsLuxelsPerWorldUnits[j][1] + + v->point[2] * tex->lightmapVecsLuxelsPerWorldUnits[j][2] + + tex->lightmapVecsLuxelsPerWorldUnits[j][3]; + if (val < mins[j]) + mins[j] = val; + if (val > maxs[j]) + maxs[j] = val; + } + } + + int nMaxLightmapDim = (s->dispinfo == -1) ? MAX_LIGHTMAP_DIM_WITHOUT_BORDER : MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER; + for (i=0 ; i<2 ; i++) + { + mins[i] = ( float )floor( mins[i] ); + maxs[i] = ( float )ceil( maxs[i] ); + + lightmapTextureMinsInLuxels[i] = ( int )mins[i]; + lightmapTextureSizeInLuxels[i] = ( int )( maxs[i] - mins[i] ); + if( lightmapTextureSizeInLuxels[i] > nMaxLightmapDim + 1 ) + { + Vector point = vec3_origin; + for (int j=0 ; jnumedges ; j++) + { + e = dsurfedges[s->firstedge+j]; + v = (e<0)?dvertexes + dedges[-e].v[1] : dvertexes + dedges[e].v[0]; + point += v->point; + Warning( "Bad surface extents point: %f %f %f\n", v->point.x, v->point.y, v->point.z ); + } + point *= 1.0f/s->numedges; + Error( "Bad surface extents - surface is too big to have a lightmap\n\tmaterial %s around point (%.1f %.1f %.1f)\n\t(dimension: %d, %d>%d)\n", + TexDataStringTable_GetString( dtexdata[texinfo[s->texinfo].texdata].nameStringTableID ), + point.x, point.y, point.z, + ( int )i, + ( int )lightmapTextureSizeInLuxels[i], + ( int )( nMaxLightmapDim + 1 ) + ); + } + } +} + + +void UpdateAllFaceLightmapExtents() +{ + for( int i=0; i < numfaces; i++ ) + { + dface_t *pFace = &dfaces[i]; + + if ( texinfo[pFace->texinfo].flags & (SURF_SKY|SURF_NOLIGHT) ) + continue; // non-lit texture + + CalcFaceExtents( pFace, pFace->m_LightmapTextureMinsInLuxels, pFace->m_LightmapTextureSizeInLuxels ); + } +} + + +//----------------------------------------------------------------------------- +// +// Helper class to iterate over leaves, used by tools +// +//----------------------------------------------------------------------------- + +#define TEST_EPSILON (0.03125) + + +class CToolBSPTree : public ISpatialQuery +{ +public: + // Returns the number of leaves + int LeafCount() const; + + // Enumerates the leaves along a ray, box, etc. + bool EnumerateLeavesAtPoint( Vector const& pt, ISpatialLeafEnumerator* pEnum, int context ); + bool EnumerateLeavesInBox( Vector const& mins, Vector const& maxs, ISpatialLeafEnumerator* pEnum, int context ); + bool EnumerateLeavesInSphere( Vector const& center, float radius, ISpatialLeafEnumerator* pEnum, int context ); + bool EnumerateLeavesAlongRay( Ray_t const& ray, ISpatialLeafEnumerator* pEnum, int context ); +}; + + +//----------------------------------------------------------------------------- +// Returns the number of leaves +//----------------------------------------------------------------------------- + +int CToolBSPTree::LeafCount() const +{ + return numleafs; +} + + +//----------------------------------------------------------------------------- +// Enumerates the leaves at a point +//----------------------------------------------------------------------------- + +bool CToolBSPTree::EnumerateLeavesAtPoint( Vector const& pt, + ISpatialLeafEnumerator* pEnum, int context ) +{ + int node = 0; + while( node >= 0 ) + { + dnode_t* pNode = &dnodes[node]; + dplane_t* pPlane = &dplanes[pNode->planenum]; + + if (DotProduct( pPlane->normal, pt ) <= pPlane->dist) + { + node = pNode->children[1]; + } + else + { + node = pNode->children[0]; + } + } + + return pEnum->EnumerateLeaf( - node - 1, context ); +} + + +//----------------------------------------------------------------------------- +// Enumerates the leaves in a box +//----------------------------------------------------------------------------- + +static bool EnumerateLeavesInBox_R( int node, Vector const& mins, + Vector const& maxs, ISpatialLeafEnumerator* pEnum, int context ) +{ + Vector cornermin, cornermax; + + while( node >= 0 ) + { + dnode_t* pNode = &dnodes[node]; + dplane_t* pPlane = &dplanes[pNode->planenum]; + + // Arbitrary split plane here + for (int i = 0; i < 3; ++i) + { + if (pPlane->normal[i] >= 0) + { + cornermin[i] = mins[i]; + cornermax[i] = maxs[i]; + } + else + { + cornermin[i] = maxs[i]; + cornermax[i] = mins[i]; + } + } + + if ( (DotProduct( pPlane->normal, cornermax ) - pPlane->dist) <= -TEST_EPSILON ) + { + node = pNode->children[1]; + } + else if ( (DotProduct( pPlane->normal, cornermin ) - pPlane->dist) >= TEST_EPSILON ) + { + node = pNode->children[0]; + } + else + { + if (!EnumerateLeavesInBox_R( pNode->children[0], mins, maxs, pEnum, context )) + { + return false; + } + + return EnumerateLeavesInBox_R( pNode->children[1], mins, maxs, pEnum, context ); + } + } + + return pEnum->EnumerateLeaf( - node - 1, context ); +} + +bool CToolBSPTree::EnumerateLeavesInBox( Vector const& mins, Vector const& maxs, + ISpatialLeafEnumerator* pEnum, int context ) +{ + return EnumerateLeavesInBox_R( 0, mins, maxs, pEnum, context ); +} + +//----------------------------------------------------------------------------- +// Enumerate leaves within a sphere +//----------------------------------------------------------------------------- + +static bool EnumerateLeavesInSphere_R( int node, Vector const& origin, + float radius, ISpatialLeafEnumerator* pEnum, int context ) +{ + while( node >= 0 ) + { + dnode_t* pNode = &dnodes[node]; + dplane_t* pPlane = &dplanes[pNode->planenum]; + + if (DotProduct( pPlane->normal, origin ) + radius - pPlane->dist <= -TEST_EPSILON ) + { + node = pNode->children[1]; + } + else if (DotProduct( pPlane->normal, origin ) - radius - pPlane->dist >= TEST_EPSILON ) + { + node = pNode->children[0]; + } + else + { + if (!EnumerateLeavesInSphere_R( pNode->children[0], + origin, radius, pEnum, context )) + { + return false; + } + + return EnumerateLeavesInSphere_R( pNode->children[1], + origin, radius, pEnum, context ); + } + } + + return pEnum->EnumerateLeaf( - node - 1, context ); +} + +bool CToolBSPTree::EnumerateLeavesInSphere( Vector const& center, float radius, ISpatialLeafEnumerator* pEnum, int context ) +{ + return EnumerateLeavesInSphere_R( 0, center, radius, pEnum, context ); +} + + +//----------------------------------------------------------------------------- +// Enumerate leaves along a ray +//----------------------------------------------------------------------------- + +static bool EnumerateLeavesAlongRay_R( int node, Ray_t const& ray, + Vector const& start, Vector const& end, ISpatialLeafEnumerator* pEnum, int context ) +{ + float front,back; + + while (node >= 0) + { + dnode_t* pNode = &dnodes[node]; + dplane_t* pPlane = &dplanes[pNode->planenum]; + + if ( pPlane->type <= PLANE_Z ) + { + front = start[pPlane->type] - pPlane->dist; + back = end[pPlane->type] - pPlane->dist; + } + else + { + front = DotProduct(start, pPlane->normal) - pPlane->dist; + back = DotProduct(end, pPlane->normal) - pPlane->dist; + } + + if (front <= -TEST_EPSILON && back <= -TEST_EPSILON) + { + node = pNode->children[1]; + } + else if (front >= TEST_EPSILON && back >= TEST_EPSILON) + { + node = pNode->children[0]; + } + else + { + // test the front side first + bool side = front < 0; + + // Compute intersection point based on the original ray + float splitfrac; + float denom = DotProduct( ray.m_Delta, pPlane->normal ); + if ( denom == 0.0f ) + { + splitfrac = 1.0f; + } + else + { + splitfrac = ( pPlane->dist - DotProduct( ray.m_Start, pPlane->normal ) ) / denom; + if (splitfrac < 0) + splitfrac = 0; + else if (splitfrac > 1) + splitfrac = 1; + } + + // Compute the split point + Vector split; + VectorMA( ray.m_Start, splitfrac, ray.m_Delta, split ); + + bool r = EnumerateLeavesAlongRay_R (pNode->children[side], ray, start, split, pEnum, context ); + if (!r) + return r; + return EnumerateLeavesAlongRay_R (pNode->children[!side], ray, split, end, pEnum, context); + } + } + + return pEnum->EnumerateLeaf( - node - 1, context ); +} + +bool CToolBSPTree::EnumerateLeavesAlongRay( Ray_t const& ray, ISpatialLeafEnumerator* pEnum, int context ) +{ + if (!ray.m_IsSwept) + { + Vector mins, maxs; + VectorAdd( ray.m_Start, ray.m_Extents, maxs ); + VectorSubtract( ray.m_Start, ray.m_Extents, mins ); + + return EnumerateLeavesInBox_R( 0, mins, maxs, pEnum, context ); + } + + // FIXME: Extruded ray not implemented yet + Assert( ray.m_IsRay ); + + Vector end; + VectorAdd( ray.m_Start, ray.m_Delta, end ); + return EnumerateLeavesAlongRay_R( 0, ray, ray.m_Start, end, pEnum, context ); +} + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- + +ISpatialQuery* ToolBSPTree() +{ + static CToolBSPTree s_ToolBSPTree; + return &s_ToolBSPTree; +} + + + +//----------------------------------------------------------------------------- +// Enumerates nodes in front to back order... +//----------------------------------------------------------------------------- + +// FIXME: Do we want this in the IBSPTree interface? + +static bool EnumerateNodesAlongRay_R( int node, Ray_t const& ray, float start, float end, + IBSPNodeEnumerator* pEnum, int context ) +{ + float front, back; + float startDotN, deltaDotN; + + while (node >= 0) + { + dnode_t* pNode = &dnodes[node]; + dplane_t* pPlane = &dplanes[pNode->planenum]; + + if ( pPlane->type <= PLANE_Z ) + { + startDotN = ray.m_Start[pPlane->type]; + deltaDotN = ray.m_Delta[pPlane->type]; + } + else + { + startDotN = DotProduct( ray.m_Start, pPlane->normal ); + deltaDotN = DotProduct( ray.m_Delta, pPlane->normal ); + } + + front = startDotN + start * deltaDotN - pPlane->dist; + back = startDotN + end * deltaDotN - pPlane->dist; + + if (front <= -TEST_EPSILON && back <= -TEST_EPSILON) + { + node = pNode->children[1]; + } + else if (front >= TEST_EPSILON && back >= TEST_EPSILON) + { + node = pNode->children[0]; + } + else + { + // test the front side first + bool side = front < 0; + + // Compute intersection point based on the original ray + float splitfrac; + if ( deltaDotN == 0.0f ) + { + splitfrac = 1.0f; + } + else + { + splitfrac = ( pPlane->dist - startDotN ) / deltaDotN; + if (splitfrac < 0.0f) + splitfrac = 0.0f; + else if (splitfrac > 1.0f) + splitfrac = 1.0f; + } + + bool r = EnumerateNodesAlongRay_R (pNode->children[side], ray, start, splitfrac, pEnum, context ); + if (!r) + return r; + + // Visit the node... + if (!pEnum->EnumerateNode( node, ray, splitfrac, context )) + return false; + + return EnumerateNodesAlongRay_R (pNode->children[!side], ray, splitfrac, end, pEnum, context); + } + } + + // Visit the leaf... + return pEnum->EnumerateLeaf( - node - 1, ray, start, end, context ); +} + + +bool EnumerateNodesAlongRay( Ray_t const& ray, IBSPNodeEnumerator* pEnum, int context ) +{ + Vector end; + VectorAdd( ray.m_Start, ray.m_Delta, end ); + return EnumerateNodesAlongRay_R( 0, ray, 0.0f, 1.0f, pEnum, context ); +} + + +//----------------------------------------------------------------------------- +// Helps us find all leaves associated with a particular cluster +//----------------------------------------------------------------------------- +CUtlVector g_ClusterLeaves; + +void BuildClusterTable( void ) +{ + int i, j; + int leafCount; + int leafList[MAX_MAP_LEAFS]; + + g_ClusterLeaves.SetCount( dvis->numclusters ); + for ( i = 0; i < dvis->numclusters; i++ ) + { + leafCount = 0; + for ( j = 0; j < numleafs; j++ ) + { + if ( dleafs[j].cluster == i ) + { + leafList[ leafCount ] = j; + leafCount++; + } + } + + g_ClusterLeaves[i].leafCount = leafCount; + if ( leafCount ) + { + g_ClusterLeaves[i].leafs.SetCount( leafCount ); + memcpy( g_ClusterLeaves[i].leafs.Base(), leafList, sizeof(int) * leafCount ); + } + } +} + +// There's a version of this in host.cpp!!! Make sure that they match. +void GetPlatformMapPath( const char *pMapPath, char *pPlatformMapPath, int dxlevel, int maxLength ) +{ + Q_StripExtension( pMapPath, pPlatformMapPath, maxLength ); + +// if( dxlevel <= 60 ) +// { +// Q_strncat( pPlatformMapPath, "_dx60", maxLength, COPY_ALL_CHARACTERS ); +// } + + Q_strncat( pPlatformMapPath, ".bsp", maxLength, COPY_ALL_CHARACTERS ); +} + +void SetHDRMode( bool bHDR ) +{ + g_bHDR = bHDR; + if( bHDR ) + { + pdlightdata = &dlightdataHDR; + g_pLeafAmbientLighting = &g_LeafAmbientLightingHDR; + pNumworldlights = &numworldlightsHDR; + dworldlights = dworldlightsHDR; +#ifdef VRAD + extern void VRadDetailProps_SetHDRMode( bool bHDR ); + VRadDetailProps_SetHDRMode( bHDR ); +#endif + } + else + { + pdlightdata = &dlightdataLDR; + g_pLeafAmbientLighting = &g_LeafAmbientLightingLDR; + pNumworldlights = &numworldlightsLDR; + dworldlights = dworldlightsLDR; +#ifdef VRAD + extern void VRadDetailProps_SetHDRMode( bool bHDR ); + VRadDetailProps_SetHDRMode( bHDR ); +#endif + } +} diff --git a/utils/common/bsplib.h b/utils/common/bsplib.h new file mode 100644 index 00000000..dfa56f36 --- /dev/null +++ b/utils/common/bsplib.h @@ -0,0 +1,371 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//=============================================================================// + +#ifndef BSPLIB_H +#define BSPLIB_H + +#ifdef _WIN32 +#pragma once +#endif + + +#include "bspfile.h" +#include "utlvector.h" + + +class ISpatialQuery; +struct Ray_t; +class Vector2D; +struct portal_t; +class CUtlBuffer; + +// this is only true in vrad +extern bool g_bHDR; + +// default width/height of luxels in world units. +#define DEFAULT_LUXEL_SIZE ( 16.0f ) + +#define SINGLE_BRUSH_MAP (MAX_BRUSH_LIGHTMAP_DIM_INCLUDING_BORDER*MAX_BRUSH_LIGHTMAP_DIM_INCLUDING_BORDER) +#define SINGLEMAP (MAX_LIGHTMAP_DIM_INCLUDING_BORDER*MAX_LIGHTMAP_DIM_INCLUDING_BORDER) + +struct entity_t +{ + Vector origin; + int firstbrush; + int numbrushes; + epair_t *epairs; + + // only valid for func_areaportals + int areaportalnum; + int portalareas[2]; + portal_t *m_pPortalsLeadingIntoAreas[2]; // portals leading into portalareas +}; + + +extern int nummodels; +extern dmodel_t dmodels[MAX_MAP_MODELS]; + +extern int visdatasize; +extern byte dvisdata[MAX_MAP_VISIBILITY]; +extern dvis_t *dvis; + +extern CUtlVector dlightdataHDR; +extern CUtlVector dlightdataLDR; +extern CUtlVector *pdlightdata; +extern CUtlVector dentdata; + +extern int numleafs; +extern dleaf_t dleafs[MAX_MAP_LEAFS]; +extern CUtlVector *g_pLeafAmbientLighting; +extern unsigned short g_LeafMinDistToWater[MAX_MAP_LEAFS]; + +extern int numplanes; +extern dplane_t dplanes[MAX_MAP_PLANES]; + +extern int numvertexes; +extern dvertex_t dvertexes[MAX_MAP_VERTS]; + +extern int g_numvertnormalindices; // dfaces reference these. These index g_vertnormals. +extern unsigned short g_vertnormalindices[MAX_MAP_VERTNORMALS]; + +extern int g_numvertnormals; +extern Vector g_vertnormals[MAX_MAP_VERTNORMALS]; + +extern int numnodes; +extern dnode_t dnodes[MAX_MAP_NODES]; + +extern CUtlVector texinfo; + +extern int numtexdata; +extern dtexdata_t dtexdata[MAX_MAP_TEXDATA]; + +// displacement map .bsp file info +extern CUtlVector g_dispinfo; +extern CUtlVector g_DispVerts; +extern CUtlVector g_DispTris; +extern CUtlVector g_DispLightmapSamplePositions; // LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS + +extern int numorigfaces; +extern dface_t dorigfaces[MAX_MAP_FACES]; + +extern int g_numprimitives; +extern dprimitive_t g_primitives[MAX_MAP_PRIMITIVES]; + +extern int g_numprimverts; +extern dprimvert_t g_primverts[MAX_MAP_PRIMVERTS]; + +extern int g_numprimindices; +extern unsigned short g_primindices[MAX_MAP_PRIMINDICES]; + +extern int numfaces; +extern dface_t dfaces[MAX_MAP_FACES]; + +extern int numfaces_hdr; +extern dface_t dfaces_hdr[MAX_MAP_FACES]; + +extern int numedges; +extern dedge_t dedges[MAX_MAP_EDGES]; + +extern int numleaffaces; +extern unsigned short dleaffaces[MAX_MAP_LEAFFACES]; + +extern int numleafbrushes; +extern unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES]; + +extern int numsurfedges; +extern int dsurfedges[MAX_MAP_SURFEDGES]; + +extern int numareas; +extern darea_t dareas[MAX_MAP_AREAS]; + +extern int numareaportals; +extern dareaportal_t dareaportals[MAX_MAP_AREAPORTALS]; + +extern int numbrushes; +extern dbrush_t dbrushes[MAX_MAP_BRUSHES]; + +extern int numbrushsides; +extern dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES]; + +extern int *pNumworldlights; +extern dworldlight_t *dworldlights; + +extern Vector g_ClipPortalVerts[MAX_MAP_PORTALVERTS]; +extern int g_nClipPortalVerts; + +extern dcubemapsample_t g_CubemapSamples[MAX_MAP_CUBEMAPSAMPLES]; +extern int g_nCubemapSamples; + +extern int g_nOverlayCount; +extern doverlay_t g_Overlays[MAX_MAP_OVERLAYS]; + +extern int g_nWaterOverlayCount; +extern dwateroverlay_t g_WaterOverlays[MAX_MAP_WATEROVERLAYS]; + +extern CUtlVector g_TexDataStringData; +extern CUtlVector g_TexDataStringTable; + +// JAY: portals in the BSP file +// These are the portal data structures (points to verts, leafs, planes) +extern int numportals; +extern dportal_t dportals[MAX_MAP_PORTALS]; + +// These are the per-cluster data (currently only the portal list) +extern int numclusters; +extern dcluster_t dclusters[MAX_MAP_CLUSTERS]; + +extern int numleafwaterdata; +extern dleafwaterdata_t dleafwaterdata[MAX_MAP_LEAFWATERDATA]; + +// This is a list of polygons. Each set of portal verts define a portal polygon +// These numbers are indices into the map's vertex list +extern int numportalverts; +extern unsigned short dportalverts[MAX_MAP_PORTALVERTS]; + +// This is a list of portal indices. Each portal is referenced twice (once by each cluster it separates) +extern int numclusterportals; +extern unsigned short dclusterportals[MAX_MAP_PORTALS*2]; + +extern CUtlVector g_FaceMacroTextureInfos; + +extern CUtlVector g_OccluderData; +extern CUtlVector g_OccluderPolyData; +extern CUtlVector g_OccluderVertexIndices; + +extern CUtlVector g_dLightmapPages; +extern CUtlVector g_dLightmapPageInfos; + +// level flags +extern uint32 g_LevelFlags; // see LVLFLAGS_xxx in bspfile.h + +// --------------------------------------------------------------- portals + +// physics collision data +extern byte *g_pPhysCollide; +extern int g_PhysCollideSize; + +// Embedded pack/pak file +void ClearPackFile( void ); +void AddFileToPack( const char *pRelativeName, const char *fullpath ); +void AddBufferToPack( const char *pRelativeName, void *data, int length, bool bTextMode ); +bool FileExistsInPack( const char *pRelativeName ); +bool ReadFileFromPack( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ); +void RemoveFileFromPack( const char *pRelativeName ); +int GetNextFilename( int id, char *pBuffer, int bufferSize, int &fileSize ); +void ForceAlignment( bool bAlign, unsigned int sectorSize ); + +//----------------------------------------------------------------------------- +// Handle to a game lump +//----------------------------------------------------------------------------- +typedef unsigned short GameLumpHandle_t; + + +//----------------------------------------------------------------------------- +// Convert four-CC code to a handle + back +//----------------------------------------------------------------------------- +GameLumpHandle_t GetGameLumpHandle( GameLumpId_t id ); +GameLumpId_t GetGameLumpId( GameLumpHandle_t handle ); +int GetGameLumpFlags( GameLumpHandle_t handle ); +int GetGameLumpVersion( GameLumpHandle_t handle ); + + +//----------------------------------------------------------------------------- +// Game lump accessor methods +//----------------------------------------------------------------------------- +void* GetGameLump( GameLumpHandle_t handle ); +int GameLumpSize( GameLumpHandle_t handle ); + + +//----------------------------------------------------------------------------- +// Game lump iteration methods +//----------------------------------------------------------------------------- +GameLumpHandle_t FirstGameLump(); +GameLumpHandle_t NextGameLump( GameLumpHandle_t handle ); +GameLumpHandle_t InvalidGameLump(); + + +//----------------------------------------------------------------------------- +// Game lump creation/destruction method +//----------------------------------------------------------------------------- +GameLumpHandle_t CreateGameLump( GameLumpId_t id, int size, int flags, int version ); +void DestroyGameLump( GameLumpHandle_t handle ); +void DestroyAllGameLumps(); + + +//----------------------------------------------------------------------------- +// Helper for the bspzip tool +//----------------------------------------------------------------------------- +void ExtractZipFileFromBSP( char *pBSPFileName, char *pZipFileName ); + + +//----------------------------------------------------------------------------- +// String table methods +//----------------------------------------------------------------------------- +const char * TexDataStringTable_GetString( int stringID ); +int TexDataStringTable_AddOrFindString( const char *pString ); + +void DecompressVis (byte *in, byte *decompressed); +int CompressVis (byte *vis, byte *dest); + +void OpenBSPFile (char *filename); +void CloseBSPFile (void); +void LoadBSPFile (char *filename); +void LoadBSPFile_FileSystemOnly (char *filename); +void LoadBSPFileTexinfo (char *filename); // just for qdata +void WriteBSPFile (char *filename, char* xzpLumpFilename = NULL); +void PrintBSPFileSizes (void); +void PrintBSPPackDirectory(void); + +void WriteLumpToFile( char *filename, int lump ); + +//=============== + +extern int num_entities; +extern entity_t entities[MAX_MAP_ENTITIES]; + +void ParseEntities (void); +void UnparseEntities (void); + +void SetKeyValue (entity_t *ent, const char *key, const char *value); +char *ValueForKey (entity_t *ent, char *key); +// will return "" if not present + +int IntForKey (entity_t *ent, char *key); +vec_t FloatForKey (entity_t *ent, char *key); +void GetVectorForKey (entity_t *ent, char *key, Vector& vec); +void GetVector2DForKey (entity_t *ent, char *key, Vector2D& vec); +void GetAnglesForKey (entity_t *ent, char *key, QAngle& vec); + +epair_t *ParseEpair (void); + +void PrintEntity (entity_t *ent); + + +// Build a list of the face's vertices (index into dvertexes). +// points must be able to hold pFace->numedges indices. +void BuildFaceCalcWindingData( dface_t *pFace, int *points ); + +// Convert a tristrip to a trilist. +// Removes degenerates. +// Fills in pTriListIndices and pnTriListIndices. +// You must free pTriListIndices with delete[]. +void TriStripToTriList( + unsigned short const *pTriStripIndices, + int nTriStripIndices, + unsigned short **pTriListIndices, + int *pnTriListIndices ); + +// Calculates the lightmap coordinates at a given set of positions given the +// lightmap basis information. +void CalcTextureCoordsAtPoints( + float const texelsPerWorldUnits[2][4], + int const subtractOffset[2], + Vector const *pPoints, + int const nPoints, + Vector2D *pCoords ); + +// Figure out lightmap extents on all (lit) faces. +void UpdateAllFaceLightmapExtents(); + + +//----------------------------------------------------------------------------- +// Gets at an interface for the tree for enumeration of leaves in volumes. +//----------------------------------------------------------------------------- +ISpatialQuery* ToolBSPTree(); + +class IBSPNodeEnumerator +{ +public: + // call back with a node and a context + virtual bool EnumerateNode( int node, Ray_t const& ray, float f, int context ) = 0; + + // call back with a leaf and a context + virtual bool EnumerateLeaf( int leaf, Ray_t const& ray, float start, float end, int context ) = 0; +}; + +//----------------------------------------------------------------------------- +// Enumerates nodes + leafs in front to back order... +//----------------------------------------------------------------------------- +bool EnumerateNodesAlongRay( Ray_t const& ray, IBSPNodeEnumerator* pEnum, int context ); + + +//----------------------------------------------------------------------------- +// Helps us find all leaves associated with a particular cluster +//----------------------------------------------------------------------------- +struct clusterlist_t +{ + int leafCount; + CUtlVector leafs; +}; + +extern CUtlVector g_ClusterLeaves; + +// Call this to build the mapping from cluster to leaves +void BuildClusterTable( ); + +void GetPlatformMapPath( const char *pMapPath, char *pPlatformMapPath, int dxlevel, int maxLength ); + +void SetHDRMode( bool bHDR ); + +// ----------------------------------------------------------------------------- // +// Helper accessors for the various structures. +// ----------------------------------------------------------------------------- // + +inline ColorRGBExp32* dface_AvgLightColor( dface_t *pFace, int nLightStyleIndex ) +{ + return (ColorRGBExp32*)&(*pdlightdata)[pFace->lightofs - (nLightStyleIndex+1) * 4]; +} + +inline const char* TexInfo_TexName( int iTexInto ) +{ + return TexDataStringTable_GetString( dtexdata[texinfo[iTexInto].texdata].nameStringTableID ); +} + + +#endif // BSPLIB_H diff --git a/utils/common/cmdlib.cpp b/utils/common/cmdlib.cpp new file mode 100644 index 00000000..7af5744e --- /dev/null +++ b/utils/common/cmdlib.cpp @@ -0,0 +1,948 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// ----------------------- +// cmdlib.c +// ----------------------- + +#include +#include "cmdlib.h" +#include +#include +#include "vstdlib/strtools.h" +#include +#include "utlvector.h" +#include "filesystem_helpers.h" +#include "utllinkedlist.h" +#include "vstdlib/icommandline.h" +#include "keyvalues.h" +#include "filesystem_tools.h" + +#if defined( MPI ) + + #include "vmpi.h" + #include "vmpi_tools_shared.h" + +#endif + + +#if defined( _WIN32 ) || defined( WIN32 ) +#include +#endif + + +// set these before calling CheckParm +int myargc; +char **myargv; + +char com_token[1024]; + +qboolean archive; +char archivedir[1024]; + +FileHandle_t g_pLogFile = 0; + +CUtlLinkedList g_CleanupFunctions; +CUtlLinkedList g_ExtraSpewHooks; + +bool g_bStopOnExit = false; +void (*g_ExtraSpewHook)(const char*) = NULL; + + +#if defined( _WIN32 ) || defined( WIN32 ) + + + +void CmdLib_FPrintf( FileHandle_t hFile, const char *pFormat, ... ) +{ + static CUtlVector buf; + if ( buf.Count() == 0 ) + buf.SetCount( 1024 ); + + va_list marker; + va_start( marker, pFormat ); + + while ( 1 ) + { + int ret = Q_vsnprintf( buf.Base(), buf.Count(), pFormat, marker ); + if ( ret >= 0 ) + { + // Write the string. + g_pFileSystem->Write( buf.Base(), ret, hFile ); + + break; + } + else + { + // Make the buffer larger. + int newSize = buf.Count() * 2; + buf.SetCount( newSize ); + if ( buf.Count() != newSize ) + { + Error( "CmdLib_FPrintf: can't allocate space for text." ); + } + } + } + + va_end( marker ); +} + + +char* CmdLib_FGets( char *pOut, int outSize, FileHandle_t hFile ) +{ + int iCur=0; + for ( ; iCur < (outSize-1); iCur++ ) + { + char c; + if ( !g_pFileSystem->Read( &c, 1, hFile ) ) + { + if ( iCur == 0 ) + return NULL; + else + break; + } + + pOut[iCur] = c; + if ( c == '\n' ) + break; + + if ( c == EOF ) + { + if ( iCur == 0 ) + return NULL; + else + break; + } + } + + pOut[iCur] = 0; + return pOut; +} + + +#include + + +// This pauses before exiting if they use -StopOnExit. Useful for debugging. +class CExitStopper +{ +public: + ~CExitStopper() + { + if ( g_bStopOnExit ) + { + Warning( "\nPress any key to quit.\n" ); + getch(); + } + } +} g_ExitStopper; + + + + +static unsigned short g_InitialColor = 0xFFFF; +static unsigned short g_LastColor = 0xFFFF; +static unsigned short g_BadColor = 0xFFFF; +static WORD g_BackgroundFlags = 0xFFFF; + +static void GetInitialColors( ) +{ + // Get the old background attributes. + CONSOLE_SCREEN_BUFFER_INFO oldInfo; + GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &oldInfo ); + g_InitialColor = g_LastColor = oldInfo.wAttributes & (FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); + g_BackgroundFlags = oldInfo.wAttributes & (BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY); + + g_BadColor = 0; + if (g_BackgroundFlags & BACKGROUND_RED) + g_BadColor |= FOREGROUND_RED; + if (g_BackgroundFlags & BACKGROUND_GREEN) + g_BadColor |= FOREGROUND_GREEN; + if (g_BackgroundFlags & BACKGROUND_BLUE) + g_BadColor |= FOREGROUND_BLUE; + if (g_BackgroundFlags & BACKGROUND_INTENSITY) + g_BadColor |= FOREGROUND_INTENSITY; +} + +static WORD SetConsoleTextColor( int red, int green, int blue, int intensity ) +{ + WORD ret = g_LastColor; + + g_LastColor = 0; + if( red ) g_LastColor |= FOREGROUND_RED; + if( green ) g_LastColor |= FOREGROUND_GREEN; + if( blue ) g_LastColor |= FOREGROUND_BLUE; + if( intensity ) g_LastColor |= FOREGROUND_INTENSITY; + + // Just use the initial color if there's a match... + if (g_LastColor == g_BadColor) + g_LastColor = g_InitialColor; + + SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), g_LastColor | g_BackgroundFlags ); + return ret; +} + + +static void RestoreConsoleTextColor( WORD color ) +{ + SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), color | g_BackgroundFlags ); + g_LastColor = color; +} + + +#if defined( CMDLIB_NODBGLIB ) + +// This can go away when everything is in bin. +void Error( char const *pMsg, ... ) +{ + va_list marker; + va_start( marker, pMsg ); + vprintf( pMsg, marker ); + va_end( marker ); + + exit( -1 ); +} + +#else + +CRITICAL_SECTION g_SpewCS; +bool g_bSpewCSInitted = false; +bool g_bSuppressPrintfOutput = false; + +SpewRetval_t CmdLib_SpewOutputFunc( SpewType_t type, char const *pMsg ) +{ + // Hopefully two threads won't call this simultaneously right at the start! + if ( !g_bSpewCSInitted ) + { + InitializeCriticalSection( &g_SpewCS ); + g_bSpewCSInitted = true; + } + + WORD old; + SpewRetval_t retVal; + + EnterCriticalSection( &g_SpewCS ); + { + if (( type == SPEW_MESSAGE ) || (type == SPEW_LOG )) + { + old = SetConsoleTextColor( 1, 1, 1, 0 ); + retVal = SPEW_CONTINUE; + } + else if( type == SPEW_WARNING ) + { + old = SetConsoleTextColor( 1, 1, 0, 1 ); + retVal = SPEW_CONTINUE; + } + else if( type == SPEW_ASSERT ) + { + old = SetConsoleTextColor( 1, 0, 0, 1 ); + retVal = SPEW_DEBUGGER; + +#ifdef MPI + // VMPI workers don't want to bring up dialogs and suchlike. + if ( g_bUseMPI && !g_bMPIMaster ) + { + VMPI_HandleCrash( pMsg, true ); + exit( 0 ); + } +#endif + } + else if( type == SPEW_ERROR ) + { + old = SetConsoleTextColor( 1, 0, 0, 1 ); + retVal = SPEW_ABORT; // doesn't matter.. we exit below so we can return an errorlevel (which dbg.dll doesn't do). + } + else + { + old = SetConsoleTextColor( 1, 1, 1, 1 ); + retVal = SPEW_CONTINUE; + } + + if ( !g_bSuppressPrintfOutput || type == SPEW_ERROR ) + printf( "%s", pMsg ); + + OutputDebugString( pMsg ); + + if ( type == SPEW_ERROR ) + { + printf( "\n" ); + OutputDebugString( "\n" ); + } + + if( g_pLogFile ) + { + CmdLib_FPrintf( g_pLogFile, "%s", pMsg ); + g_pFileSystem->Flush( g_pLogFile ); + } + + // Dispatch to other spew hooks. + FOR_EACH_LL( g_ExtraSpewHooks, i ) + g_ExtraSpewHooks[i]( pMsg ); + + RestoreConsoleTextColor( old ); + } + LeaveCriticalSection( &g_SpewCS ); + + if ( type == SPEW_ERROR ) + { + CmdLib_Exit( 1 ); + } + + return retVal; +} + + +void InstallSpewFunction() +{ + setvbuf( stdout, NULL, _IONBF, 0 ); + setvbuf( stderr, NULL, _IONBF, 0 ); + + SpewOutputFunc( CmdLib_SpewOutputFunc ); + GetInitialColors(); +} + + +void InstallExtraSpewHook( SpewHookFn pFn ) +{ + g_ExtraSpewHooks.AddToTail( pFn ); +} + + +void CmdLib_AllocError( unsigned long size ) +{ + Error( "Error trying to allocate %d bytes.\n", size ); +} + +int CmdLib_NewHandler( size_t size ) +{ + CmdLib_AllocError( size ); + return 0; +} + +void InstallAllocationFunctions() +{ + _set_new_mode( 1 ); // so if malloc() fails, we exit. + _set_new_handler( CmdLib_NewHandler ); +} + + +void SetSpewFunctionLogFile( char const *pFilename ) +{ + Assert( (!g_pLogFile) ); + g_pLogFile = g_pFileSystem->Open( pFilename, "a" ); + + Assert( g_pLogFile ); + if (!g_pLogFile) + Error("Can't create LogFile:\"%s\"\n", pFilename ); + + CmdLib_FPrintf( g_pLogFile, "\n\n\n" ); +} + + +void CloseSpewFunctionLogFile() +{ + if ( g_pFileSystem && g_pLogFile ) + { + g_pFileSystem->Close( g_pLogFile ); + g_pLogFile = FILESYSTEM_INVALID_HANDLE; + } +} + + +void CmdLib_AtCleanup( CleanupFn pFn ) +{ + g_CleanupFunctions.AddToTail( pFn ); +} + + +void CmdLib_Cleanup() +{ + CloseSpewFunctionLogFile(); + + CmdLib_TermFileSystem(); + + FOR_EACH_LL( g_CleanupFunctions, i ) + g_CleanupFunctions[i](); + +#if defined( MPI ) + // Unfortunately, when you call exit(), even if you have things registered with atexit(), + // threads go into a seemingly undefined state where GetExitCodeThread gives STILL_ACTIVE + // and WaitForSingleObject will stall forever on the thread. Because of this, we must cleanup + // everything that uses threads before exiting. + VMPI_Finalize(); +#endif +} + + +void CmdLib_Exit( int exitCode ) +{ + TerminateProcess( GetCurrentProcess(), 1 ); +} + + + +#endif + +#endif + + + + +/* +=================== +ExpandWildcards + +Mimic unix command line expansion +=================== +*/ +#define MAX_EX_ARGC 1024 +int ex_argc; +char *ex_argv[MAX_EX_ARGC]; +#ifdef _WIN32 +#include "io.h" +void ExpandWildcards (int *argc, char ***argv) +{ + struct _finddata_t fileinfo; + int handle; + int i; + char filename[1024]; + char filebase[1024]; + char *path; + + ex_argc = 0; + for (i=0 ; i<*argc ; i++) + { + path = (*argv)[i]; + if ( path[0] == '-' + || ( !strstr(path, "*") && !strstr(path, "?") ) ) + { + ex_argv[ex_argc++] = path; + continue; + } + + handle = _findfirst (path, &fileinfo); + if (handle == -1) + return; + + Q_ExtractFilePath (path, filebase, sizeof( filebase )); + + do + { + sprintf (filename, "%s%s", filebase, fileinfo.name); + ex_argv[ex_argc++] = copystring (filename); + } while (_findnext( handle, &fileinfo ) != -1); + + _findclose (handle); + } + + *argc = ex_argc; + *argv = ex_argv; +} +#else +void ExpandWildcards (int *argc, char ***argv) +{ +} +#endif + + +// only printf if in verbose mode +qboolean verbose = false; +void qprintf (char *format, ...) +{ + if (!verbose) + return; + + va_list argptr; + va_start (argptr,format); + + char str[2048]; + Q_vsnprintf( str, sizeof(str), format, argptr ); + +#if defined( CMDLIB_NODBGLIB ) + printf( "%s", str ); +#else + Msg( "%s", str ); +#endif + + va_end (argptr); +} + + +// ---------------------------------------------------------------------------------------------------- // +// Helpers. +// ---------------------------------------------------------------------------------------------------- // + +static void CmdLib_getwd( char *out, int outSize ) +{ +#if defined( _WIN32 ) || defined( WIN32 ) + _getcwd( out, outSize ); + Q_strncat( out, "\\", outSize, COPY_ALL_CHARACTERS ); +#else + getwd(out); + strcat(out, "/"); +#endif + Q_FixSlashes( out ); +} + +char *ExpandArg (char *path) +{ + static char full[1024]; + + if (path[0] != '/' && path[0] != '\\' && path[1] != ':') + { + CmdLib_getwd (full, sizeof( full )); + Q_strncat (full, path, sizeof( full ), COPY_ALL_CHARACTERS); + } + else + Q_strncpy (full, path, sizeof( full )); + return full; +} + + +char *ExpandPath (char *path) +{ + static char full[1024]; + if (path[0] == '/' || path[0] == '\\' || path[1] == ':') + return path; + sprintf (full, "%s%s", qdir, path); + return full; +} + + + +char *copystring(const char *s) +{ + char *b; + b = (char *)malloc(strlen(s)+1); + strcpy (b, s); + return b; +} + + +void GetHourMinuteSeconds( int nInputSeconds, int &nHours, int &nMinutes, int &nSeconds ) +{ +} + + +void GetHourMinuteSecondsString( int nInputSeconds, char *pOut, int outLen ) +{ + int nMinutes = nInputSeconds / 60; + int nSeconds = nInputSeconds - nMinutes * 60; + int nHours = nMinutes / 60; + nMinutes -= nHours * 60; + + char *extra[2] = { "", "s" }; + + if ( nHours > 0 ) + Q_snprintf( pOut, outLen, "%d hour%s, %d minute%s, %d second%s", nHours, extra[nHours != 1], nMinutes, extra[nMinutes != 1], nSeconds, extra[nSeconds != 1] ); + else if ( nMinutes > 0 ) + Q_snprintf( pOut, outLen, "%d minute%s, %d second%s", nMinutes, extra[nMinutes != 1], nSeconds, extra[nSeconds != 1] ); + else + Q_snprintf( pOut, outLen, "%d second%s", nSeconds, extra[nSeconds != 1] ); +} + + +void Q_mkdir (char *path) +{ +#if defined( _WIN32 ) || defined( WIN32 ) + if (_mkdir (path) != -1) + return; +#else + if (mkdir (path, 0777) != -1) + return; +#endif +// if (errno != EEXIST) + Error ("mkdir failed %s\n", path ); +} + +void CmdLib_InitFileSystem( const char *pFilename, int maxMemoryUsage ) +{ + FileSystem_Init( pFilename, maxMemoryUsage ); + if ( !g_pFileSystem ) + Error( "CmdLib_InitFileSystem failed." ); +} + +void CmdLib_TermFileSystem() +{ + FileSystem_Term(); +} + +CreateInterfaceFn CmdLib_GetFileSystemFactory() +{ + return FileSystem_GetFactory(); +} + + +/* +============ +FileTime + +returns -1 if not present +============ +*/ +int FileTime (char *path) +{ + struct stat buf; + + if (stat (path,&buf) == -1) + return -1; + + return buf.st_mtime; +} + + + +/* +============== +COM_Parse + +Parse a token out of a string +============== +*/ +char *COM_Parse (char *data) +{ + return (char*)ParseFile( data, com_token, NULL ); +} + + +/* +============================================================================= + + MISC FUNCTIONS + +============================================================================= +*/ + + +/* +================= +CheckParm + +Checks for the given parameter in the program's command line arguments +Returns the argument number (1 to argc-1) or 0 if not present +================= +*/ +int CheckParm (char *check) +{ + int i; + + for (i = 1;iSize( f ); +} + + +FileHandle_t SafeOpenWrite (char *filename) +{ + FileHandle_t f = g_pFileSystem->Open(filename, "wb"); + + if (!f) + { + //Error ("Error opening %s: %s",filename,strerror(errno)); + // BUGBUG: No way to get equivalent of errno from IFileSystem! + Error ("Error opening %s! (Check for write enable)\n",filename); + } + + return f; +} + +#define MAX_CMDLIB_BASE_PATHS 10 +static char g_pBasePaths[MAX_CMDLIB_BASE_PATHS][MAX_PATH]; +static int g_NumBasePaths = 0; + +void CmdLib_AddBasePath( const char *pPath ) +{ +// printf( "CmdLib_AddBasePath( \"%s\" )\n", pPath ); + if( g_NumBasePaths < MAX_CMDLIB_BASE_PATHS ) + { + Q_strncpy( g_pBasePaths[g_NumBasePaths], pPath, MAX_PATH ); + Q_FixSlashes( g_pBasePaths[g_NumBasePaths] ); + g_NumBasePaths++; + } + else + { + Assert( 0 ); + } +} + +bool CmdLib_HasBasePath( const char *pFileName_, int &pathLength ) +{ + char *pFileName = ( char * )_alloca( strlen( pFileName_ ) + 1 ); + strcpy( pFileName, pFileName_ ); + Q_FixSlashes( pFileName ); + pathLength = 0; + int i; + for( i = 0; i < g_NumBasePaths; i++ ) + { + // see if we can rip the base off of the filename. + if( Q_strncasecmp( g_pBasePaths[i], pFileName, strlen( g_pBasePaths[i] ) ) == 0 ) + { + pathLength = strlen( g_pBasePaths[i] ); + return true; + } + } + return false; +} + +int CmdLib_GetNumBasePaths( void ) +{ + return g_NumBasePaths; +} + +const char *CmdLib_GetBasePath( int i ) +{ + Assert( i >= 0 && i < g_NumBasePaths ); + return g_pBasePaths[i]; +} + +FileHandle_t SafeOpenRead( char *filename ) +{ + int pathLength; + FileHandle_t f = 0; + if( CmdLib_HasBasePath( filename, pathLength ) ) + { + filename = filename + pathLength; + int i; + for( i = 0; i < g_NumBasePaths; i++ ) + { + char tmp[MAX_PATH]; + strcpy( tmp, g_pBasePaths[i] ); + strcat( tmp, filename ); + f = g_pFileSystem->Open( tmp, "rb" ); + if( f ) + { + return f; + } + } + Error ("Error opening %s\n",filename ); + return f; + } + else + { + f = g_pFileSystem->Open( filename, "rb" ); + if ( !f ) + Error ("Error opening %s",filename ); + + return f; + } +} + +void SafeRead( FileHandle_t f, void *buffer, int count) +{ + if ( g_pFileSystem->Read (buffer, count, f) != (size_t)count) + Error ("File read failure"); +} + + +void SafeWrite ( FileHandle_t f, void *buffer, int count) +{ + if (g_pFileSystem->Write (buffer, count, f) != (size_t)count) + Error ("File write failure"); +} + + +/* +============== +FileExists +============== +*/ +qboolean FileExists (char *filename) +{ + FileHandle_t hFile = g_pFileSystem->Open( filename, "rb" ); + if ( hFile == FILESYSTEM_INVALID_HANDLE ) + { + return false; + } + else + { + g_pFileSystem->Close( hFile ); + return true; + } +} + +/* +============== +LoadFile +============== +*/ +int LoadFile (char *filename, void **bufferptr) +{ + int length = 0; + void *buffer; + + FileHandle_t f = SafeOpenRead (filename); + if ( FILESYSTEM_INVALID_HANDLE != f ) + { + length = Q_filelength (f); + buffer = malloc (length+1); + ((char *)buffer)[length] = 0; + SafeRead (f, buffer, length); + g_pFileSystem->Close (f); + *bufferptr = buffer; + } + else + { + *bufferptr = NULL; + } + return length; +} + + + +/* +============== +SaveFile +============== +*/ +void SaveFile (char *filename, void *buffer, int count) +{ + FileHandle_t f = SafeOpenWrite (filename); + SafeWrite (f, buffer, count); + g_pFileSystem->Close (f); +} + +/* +==================== +Extract file parts +==================== +*/ +// FIXME: should include the slash, otherwise +// backing to an empty path will be wrong when appending a slash + + + +/* +============== +ParseNum / ParseHex +============== +*/ +int ParseHex (char *hex) +{ + char *str; + int num; + + num = 0; + str = hex; + + while (*str) + { + num <<= 4; + if (*str >= '0' && *str <= '9') + num += *str-'0'; + else if (*str >= 'a' && *str <= 'f') + num += 10 + *str-'a'; + else if (*str >= 'A' && *str <= 'F') + num += 10 + *str-'A'; + else + Error ("Bad hex number: %s",hex); + str++; + } + + return num; +} + + +int ParseNum (char *str) +{ + if (str[0] == '$') + return ParseHex (str+1); + if (str[0] == '0' && str[1] == 'x') + return ParseHex (str+2); + return atol (str); +} + +/* +============ +CreatePath +============ +*/ +void CreatePath (char *path) +{ + char *ofs, c; + + // strip the drive + if (path[1] == ':') + path += 2; + + for (ofs = path+1 ; *ofs ; ofs++) + { + c = *ofs; + if (c == '/' || c == '\\') + { // create the directory + *ofs = 0; + Q_mkdir (path); + *ofs = c; + } + } +} + +//----------------------------------------------------------------------------- +// Creates a path, path may already exist +//----------------------------------------------------------------------------- +#if defined( _WIN32 ) || defined( WIN32 ) +void SafeCreatePath( char *path ) +{ + char *ptr; + + // skip past the drive path, but don't strip + if ( path[1] == ':' ) + { + ptr = strchr( path, '\\' ); + } + else + { + ptr = path; + } + while ( ptr ) + { + ptr = strchr( ptr+1, '\\' ); + if ( ptr ) + { + *ptr = '\0'; + _mkdir( path ); + *ptr = '\\'; + } + } +} +#endif + +/* +============ +QCopyFile + + Used to archive source files +============ +*/ +void QCopyFile (char *from, char *to) +{ + void *buffer; + int length; + + length = LoadFile (from, &buffer); + CreatePath (to); + SaveFile (to, buffer, length); + free (buffer); +} + + + diff --git a/utils/common/cmdlib.h b/utils/common/cmdlib.h new file mode 100644 index 00000000..3bd57076 --- /dev/null +++ b/utils/common/cmdlib.h @@ -0,0 +1,170 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//=============================================================================// + +#ifndef CMDLIB_H +#define CMDLIB_H + +#ifdef _WIN32 +#pragma once +#endif + +// cmdlib.h + +#include "basetypes.h" + +// This can go away when everything is in bin. +#if defined( CMDLIB_NODBGLIB ) + void Error( char const *pMsg, ... ); +#else + #include "tier0/dbg.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include "filesystem.h" +#include "filesystem_tools.h" + + +// Tools should use this as the read path ID. It'll look into the paths specified by gameinfo.txt +#define TOOLS_READ_PATH_ID "GAME" + + +// Tools should use this to fprintf data to files. +void CmdLib_FPrintf( FileHandle_t hFile, const char *pFormat, ... ); +char* CmdLib_FGets( char *pOut, int outSize, FileHandle_t hFile ); + + +// This can be set so Msg() sends output to hook functions (like the VMPI MySQL database), +// but doesn't actually printf the output. +extern bool g_bSuppressPrintfOutput; + +extern IBaseFileSystem *g_pFileSystem; + +// These call right into the functions in filesystem_tools.h +void CmdLib_InitFileSystem( const char *pFilename, int maxMemoryUsage = 0 ); +void CmdLib_TermFileSystem(); // GracefulExit calls this. +CreateInterfaceFn CmdLib_GetFileSystemFactory(); + + +#ifdef _WIN32 +#pragma warning(disable : 4244) // MIPS +#pragma warning(disable : 4136) // X86 +#pragma warning(disable : 4051) // ALPHA + +#pragma warning(disable : 4018) // signed/unsigned mismatch +#pragma warning(disable : 4305) // truncate from double to float + +#pragma warning(disable : 4389) // singned/unsigned mismatch in == +#pragma warning(disable: 4512) // assignment operator could not be generated +#endif + + +// the dec offsetof macro doesnt work very well... +#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier) + + +// set these before calling CheckParm +extern int myargc; +extern char **myargv; + +int Q_filelength (FileHandle_t f); +int FileTime (char *path); + +void Q_mkdir( char *path ); + +char *ExpandArg (char *path); // expand relative to CWD +char *ExpandPath (char *path); // expand relative to gamedir + +char *ExpandPathAndArchive (char *path); + +// Fills in pOut with "X hours, Y minutes, Z seconds". Leaves out hours or minutes if they're zero. +void GetHourMinuteSecondsString( int nInputSeconds, char *pOut, int outLen ); + + + +int CheckParm (char *check); + +FileHandle_t SafeOpenWrite (char *filename); +FileHandle_t SafeOpenRead (char *filename); +void SafeRead( FileHandle_t f, void *buffer, int count); +void SafeWrite( FileHandle_t f, void *buffer, int count); + +int LoadFile (char *filename, void **bufferptr); +void SaveFile (char *filename, void *buffer, int count); +qboolean FileExists (char *filename); + +int ParseNum (char *str); + +// Do a printf in the specified color. +#define CP_ERROR stderr, 1, 0, 0, 1 // default colors.. +#define CP_WARNING stderr, 1, 1, 0, 1 +#define CP_STARTUP stdout, 0, 1, 1, 1 +#define CP_NOTIFY stdout, 1, 1, 1, 1 +void ColorPrintf( FILE *pFile, bool red, bool green, bool blue, bool intensity, char const *pFormat, ... ); + +// Initialize spew output. +void InstallSpewFunction(); + +// This registers an extra callback for spew output. +typedef void (*SpewHookFn)( const char * ); +void InstallExtraSpewHook( SpewHookFn pFn ); + +// Install allocation hooks so we error out if an allocation can't happen. +void InstallAllocationFunctions(); + +// This shuts down mgrs that use threads gracefully. If you just call exit(), the threads can +// get in a state where you can't tell if they are shutdown or not, and it can stall forever. +typedef void (*CleanupFn)(); +void CmdLib_AtCleanup( CleanupFn pFn ); // register a callback when Cleanup() is called. +void CmdLib_Cleanup(); +void CmdLib_Exit( int exitCode ); // Use this to cleanup and call exit(). + +// Append all spew output to the specified file. +void SetSpewFunctionLogFile( char const *pFilename ); + +char *COM_Parse (char *data); + +extern char com_token[1024]; + +char *copystring(const char *s); + +void CreatePath( char *path ); +void QCopyFile( char *from, char *to ); +void SafeCreatePath( char *path ); + +extern qboolean archive; +extern char archivedir[1024]; + +extern qboolean verbose; + +void qprintf( char *format, ... ); + +void ExpandWildcards (int *argc, char ***argv); + +void CmdLib_AddBasePath( const char *pBasePath ); +bool CmdLib_HasBasePath( const char *pFileName, int &pathLength ); +int CmdLib_GetNumBasePaths( void ); +const char *CmdLib_GetBasePath( int i ); + +extern bool g_bStopOnExit; + +// for compression routines +typedef struct +{ + byte *data; + int count; +} cblock_t; + + +#endif // CMDLIB_H diff --git a/utils/common/consolewnd.cpp b/utils/common/consolewnd.cpp new file mode 100644 index 00000000..d4b6c0cf --- /dev/null +++ b/utils/common/consolewnd.cpp @@ -0,0 +1,322 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include +#include "consolewnd.h" + + +#define EDITCONTROL_BORDER_SIZE 5 + + +// ------------------------------------------------------------------------------------------------ // +// Functions to manage the console window. +// ------------------------------------------------------------------------------------------------ // + +class CConsoleWnd : public IConsoleWnd +{ +public: + CConsoleWnd(); + ~CConsoleWnd(); + + bool Init( void *hInstance, int dialogResourceID, int editControlID, bool bVisible ); + void Term(); + + virtual void Release(); + + virtual void SetVisible( bool bVisible ); + virtual bool IsVisible() const; + + virtual void PrintToConsole( const char *pMsg ); + virtual void SetTitle( const char *pTitle ); + + virtual void SetDeleteOnClose( bool bDelete ); + + +private: + + int WindowProc( + HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam // second message parameter + ); + + static int CALLBACK StaticWindowProc( + HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam // second message parameter + ); + + void RepositionEditControl(); + + +private: + + HWND m_hWnd; + HWND m_hEditControl; + bool m_bVisible; + bool m_bDeleteOnClose; + int m_nCurrentChars; +}; + + +CConsoleWnd::CConsoleWnd() +{ + m_hWnd = m_hEditControl = NULL; + m_bVisible = false; + m_bDeleteOnClose = false; + m_nCurrentChars = 0; +} + + +CConsoleWnd::~CConsoleWnd() +{ + Term(); +} + + +bool CConsoleWnd::Init( void *hInstance, int dialogResourceID, int editControlID, bool bVisible ) +{ + // Create the window. + m_hWnd = CreateDialog( + (HINSTANCE)hInstance, + MAKEINTRESOURCE( dialogResourceID ), + NULL, + &CConsoleWnd::StaticWindowProc ); + + if ( !m_hWnd ) + return false; + + SetWindowLong( m_hWnd, GWL_USERDATA, (LONG)this ); + if ( bVisible ) + ShowWindow( m_hWnd, SW_SHOW ); + + // Get a handle to the edit control. + m_hEditControl = GetDlgItem( m_hWnd, editControlID ); + if ( !m_hEditControl ) + return false; + + RepositionEditControl(); + + m_bVisible = bVisible; + return true; +} + + +void CConsoleWnd::Term() +{ + if ( m_hWnd ) + { + DestroyWindow( m_hWnd ); + m_hWnd = NULL; + } +} + + +void CConsoleWnd::Release() +{ + delete this; +} + + +void CConsoleWnd::SetVisible( bool bVisible ) +{ + ShowWindow( m_hWnd, bVisible ? SW_RESTORE : SW_HIDE ); + + if ( bVisible ) + SetWindowPos( m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW ); + else + SetWindowPos( m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW | SWP_NOOWNERZORDER ); + + m_bVisible = bVisible; +} + + +bool CConsoleWnd::IsVisible() const +{ + return m_bVisible; +} + + +void CConsoleWnd::PrintToConsole( const char *pMsg ) +{ + if ( m_nCurrentChars >= 16*1024 ) + { + // Clear the edit control otherwise it'll stop outputting anything. + m_nCurrentChars = 0; + + int nLen = SendMessage( m_hEditControl, EM_GETLIMITTEXT, 0, 0 ); + SendMessage( m_hEditControl, EM_SETSEL, 0, nLen ); + SendMessage( m_hEditControl, EM_REPLACESEL, FALSE, (LPARAM)"" ); + } + + FormatAndSendToEditControl( m_hEditControl, pMsg ); + m_nCurrentChars += strlen( pMsg ); +} + + +void CConsoleWnd::SetTitle( const char *pTitle ) +{ + SetWindowText( m_hWnd, pTitle ); +} + + +int CConsoleWnd::WindowProc( + HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam // second message parameter + ) +{ + lParam = lParam; // avoid compiler warning + + if ( hwndDlg != m_hWnd ) + return false; + + switch ( uMsg ) + { + case WM_SYSCOMMAND: + { + if ( wParam == SC_CLOSE ) + { + if ( m_bDeleteOnClose ) + { + Release(); + } + else + { + SetVisible( false ); + return true; + } + } + } + break; + + case WM_SHOWWINDOW: + { + m_bVisible = (wParam != 0); + } + break; + + case WM_SIZE: + case WM_INITDIALOG: + { + RepositionEditControl(); + } + break; + } + + return false; +} + + +int CConsoleWnd::StaticWindowProc( + HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam // second message parameter + ) +{ + CConsoleWnd *pDlg = (CConsoleWnd*)GetWindowLong( hwndDlg, GWL_USERDATA ); + if ( pDlg ) + return pDlg->WindowProc( hwndDlg, uMsg, wParam, lParam ); + else + return false; +} + + +void CConsoleWnd::RepositionEditControl() +{ + RECT rcMain; + GetClientRect( m_hWnd, &rcMain ); + + RECT rcNew; + rcNew.left = rcMain.left + EDITCONTROL_BORDER_SIZE; + rcNew.right = rcMain.right - EDITCONTROL_BORDER_SIZE; + rcNew.top = rcMain.top + EDITCONTROL_BORDER_SIZE; + rcNew.bottom = rcMain.bottom - EDITCONTROL_BORDER_SIZE; + + SetWindowPos( + m_hEditControl, + NULL, + rcNew.left, + rcNew.top, + rcNew.right - rcNew.left, + rcNew.bottom - rcNew.top, + SWP_NOZORDER ); +} + + +void CConsoleWnd::SetDeleteOnClose( bool bDelete ) +{ + m_bDeleteOnClose = bDelete; +} + + +// ------------------------------------------------------------------------------------ // +// Module interface. +// ------------------------------------------------------------------------------------ // + +void SendToEditControl( HWND hEditControl, const char *pText ) +{ + int nLen = SendMessage( hEditControl, EM_GETLIMITTEXT, 0, 0 ); + SendMessage( hEditControl, EM_SETSEL, nLen, nLen ); + SendMessage( hEditControl, EM_REPLACESEL, FALSE, (LPARAM)pText ); +} + + +void FormatAndSendToEditControl( void *hWnd, const char *pText ) +{ + HWND hEditControl = (HWND)hWnd; + + // Translate \n to \r\n. + char outMsg[1024]; + const char *pIn = pText; + char *pOut = outMsg; + while ( *pIn ) + { + if ( *pIn == '\n' ) + { + *pOut = '\r'; + pOut++; + } + *pOut = *pIn; + + ++pIn; + ++pOut; + + if ( pOut - outMsg >= 1020 ) + { + *pOut = 0; + SendToEditControl( hEditControl, outMsg ); + pOut = outMsg; + } + } + *pOut = 0; + SendToEditControl( hEditControl, outMsg ); +} + + +IConsoleWnd* CreateConsoleWnd( void *hInstance, int dialogResourceID, int editControlID, bool bVisible ) +{ + CConsoleWnd *pWnd = new CConsoleWnd; + + if ( pWnd->Init( hInstance, dialogResourceID, editControlID, bVisible ) ) + { + return pWnd; + } + else + { + pWnd->Release(); + return NULL; + } +} + + + + diff --git a/utils/common/consolewnd.h b/utils/common/consolewnd.h new file mode 100644 index 00000000..873ff1e9 --- /dev/null +++ b/utils/common/consolewnd.h @@ -0,0 +1,45 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef CONSOLEWND_H +#define CONSOLEWND_H +#ifdef _WIN32 +#pragma once +#endif + + +class IConsoleWnd +{ +public: + virtual void Release() = 0; + + // Print a message to the console. + virtual void PrintToConsole( const char *pMsg ) = 0; + + // Set the window title. + virtual void SetTitle( const char *pTitle ) = 0; + + // Show and hide the console window. + virtual void SetVisible( bool bVisible ) = 0; + virtual bool IsVisible() const = 0; + + // Normally, the window just hides itself when closed. You can use this to make the window + // automatically go away when they close it. + virtual void SetDeleteOnClose( bool bDelete ) = 0; +}; + + +// Utility functions. + +// This converts adds \r's where necessary and sends the text to the edit control. +void FormatAndSendToEditControl( void *hWnd, const char *pText ); + + +IConsoleWnd* CreateConsoleWnd( void *hInstance, int dialogResourceID, int editControlID, bool bVisible ); + + +#endif // CONSOLEWND_H diff --git a/utils/common/filesystem_tools.cpp b/utils/common/filesystem_tools.cpp new file mode 100644 index 00000000..d1643f44 --- /dev/null +++ b/utils/common/filesystem_tools.cpp @@ -0,0 +1,214 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifdef _WIN32 +#include +#include +#include // _chmod +#elif _LINUX +#include +#endif + +#include +#include +#include "vstdlib/strtools.h" +#include "filesystem_tools.h" +#include "vstdlib/ICommandLine.h" +#include "KeyValues.h" +#include "tier2/tier2.h" + +#ifdef MPI + #include "vmpi.h" + #include "vmpi_tools_shared.h" + #include "vmpi_filesystem.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include + + +// ---------------------------------------------------------------------------------------------------- // +// Module interface. +// ---------------------------------------------------------------------------------------------------- // + +IBaseFileSystem *g_pFileSystem = NULL; + +// These are only used for tools that need the search paths that the engine's file system provides. +CSysModule *g_pFullFileSystemModule = NULL; + +// --------------------------------------------------------------------------- +// +// These are the base paths that everything will be referenced relative to (textures especially) +// All of these directories include the trailing slash +// +// --------------------------------------------------------------------------- + +// This is the the path of the initial source file (relative to the cwd) +char qdir[1024]; + +// This is the base engine + mod-specific game dir (e.g. "c:\tf2\mytfmod\") +char gamedir[1024]; + + +bool FileSystem_Init_Normal( const char *pFilename, FSInitType_t initType, bool bOnlyUseDirectoryName ) +{ + if ( initType == FS_INIT_FULL ) + { + // First, get the name of the module + char fileSystemDLLName[MAX_PATH]; + bool bSteam; + if ( FileSystem_GetFileSystemDLLName( fileSystemDLLName, MAX_PATH, bSteam ) != FS_OK ) + return false; + + // If we're under Steam we need extra setup to let us find the proper modules + FileSystem_SetupSteamInstallPath(); + + // Next, load the module, call Connect/Init. + CFSLoadModuleInfo loadModuleInfo; + loadModuleInfo.m_pFileSystemDLLName = fileSystemDLLName; + loadModuleInfo.m_pDirectoryName = pFilename; + loadModuleInfo.m_bOnlyUseDirectoryName = bOnlyUseDirectoryName; + loadModuleInfo.m_ConnectFactory = Sys_GetFactoryThis(); + loadModuleInfo.m_bSteam = bSteam; + loadModuleInfo.m_bToolsMode = true; + if ( FileSystem_LoadFileSystemModule( loadModuleInfo ) != FS_OK ) + return false; + + // Next, mount the content + CFSMountContentInfo mountContentInfo; + mountContentInfo.m_pDirectoryName= loadModuleInfo.m_GameInfoPath; + mountContentInfo.m_pFileSystem = loadModuleInfo.m_pFileSystem; + mountContentInfo.m_bToolsMode = true; + if ( FileSystem_MountContent( mountContentInfo ) != FS_OK ) + return false; + + // Finally, load the search paths. + CFSSearchPathsInit searchPathsInit; + searchPathsInit.m_pDirectoryName = loadModuleInfo.m_GameInfoPath; + searchPathsInit.m_pFileSystem = loadModuleInfo.m_pFileSystem; + if ( FileSystem_LoadSearchPaths( searchPathsInit ) != FS_OK ) + return false; + + // Store the data we got from filesystem_init. + g_pFileSystem = g_pFullFileSystem = loadModuleInfo.m_pFileSystem; + g_pFullFileSystemModule = loadModuleInfo.m_pModule; + + FileSystem_AddSearchPath_Platform( g_pFullFileSystem, loadModuleInfo.m_GameInfoPath ); + + // Set qdir. + if ( !pFilename ) + pFilename = "."; + + Q_MakeAbsolutePath( qdir, sizeof( qdir ), pFilename, NULL ); + Q_StripFilename( qdir ); + strlwr( qdir ); + if ( qdir[0] != 0 ) + Q_AppendSlash( qdir, sizeof( qdir ) ); + + // Set gamedir. + Q_MakeAbsolutePath( gamedir, sizeof( gamedir ), loadModuleInfo.m_GameInfoPath ); + Q_AppendSlash( gamedir, sizeof( gamedir ) ); + } + else + { + if ( !Sys_LoadInterface( + "filesystem_stdio", + FILESYSTEM_INTERFACE_VERSION, + &g_pFullFileSystemModule, + (void**)&g_pFullFileSystem ) ) + { + return false; + } + + if ( g_pFullFileSystem->Init() != INIT_OK ) + return false; + + g_pFullFileSystem->RemoveAllSearchPaths(); + g_pFullFileSystem->AddSearchPath( "../platform", "PLATFORM" ); + g_pFullFileSystem->AddSearchPath( ".", "GAME" ); + + g_pFileSystem = g_pFullFileSystem; + } + + return true; +} + + +bool FileSystem_Init( const char *pBSPFilename, int maxMemoryUsage, FSInitType_t initType, bool bOnlyUseFilename ) +{ + Assert( CommandLine()->GetCmdLine() != NULL ); // Should have called CreateCmdLine by now. + + // If this app uses VMPI, then let VMPI intercept all filesystem calls. +#if defined( MPI ) + if ( g_bUseMPI ) + { + if ( g_bMPIMaster ) + { + if ( !FileSystem_Init_Normal( pBSPFilename, initType, bOnlyUseFilename ) ) + return false; + + g_pFileSystem = g_pFullFileSystem = VMPI_FileSystem_Init( maxMemoryUsage, g_pFullFileSystem ); + SendQDirInfo(); + } + else + { + g_pFileSystem = g_pFullFileSystem = VMPI_FileSystem_Init( maxMemoryUsage, NULL ); + RecvQDirInfo(); + } + return true; + } +#endif + + return FileSystem_Init_Normal( pBSPFilename, initType, bOnlyUseFilename ); +} + + +void FileSystem_Term() +{ +#if defined( MPI ) + if ( g_bUseMPI ) + { + g_pFileSystem = g_pFullFileSystem = VMPI_FileSystem_Term(); + } +#endif + + if ( g_pFullFileSystem ) + { + g_pFullFileSystem->Shutdown(); + g_pFullFileSystem = NULL; + g_pFileSystem = NULL; + } + + if ( g_pFullFileSystemModule ) + { + Sys_UnloadModule( g_pFullFileSystemModule ); + g_pFullFileSystemModule = NULL; + } +} + + +CreateInterfaceFn FileSystem_GetFactory() +{ +#if defined( MPI ) + if ( g_bUseMPI ) + return VMPI_FileSystem_GetFactory(); +#endif + return Sys_GetFactory( g_pFullFileSystemModule ); +} + + +bool FileSystem_SetGame( const char *szModDir ) +{ + g_pFullFileSystem->RemoveAllSearchPaths(); + if ( FileSystem_SetBasePaths( g_pFullFileSystem ) != FS_OK ) + return false; + + CFSSearchPathsInit fsInit; + fsInit.m_pDirectoryName = szModDir; + fsInit.m_pFileSystem = g_pFullFileSystem; + return ( FileSystem_LoadSearchPaths( fsInit ) == FS_OK ); +} + diff --git a/utils/common/filesystem_tools.h b/utils/common/filesystem_tools.h new file mode 100644 index 00000000..117be7df --- /dev/null +++ b/utils/common/filesystem_tools.h @@ -0,0 +1,57 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef FILESYSTEM_TOOLS_H +#define FILESYSTEM_TOOLS_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "filesystem.h" +#include "filesystem_init.h" + + +// This is the the path of the initial source file +extern char qdir[1024]; + +// This is the base engine + mod-specific game dir (e.g. "d:\tf2\mytfmod\") +extern char gamedir[1024]; + + +// ---------------------------------------------------------------------------------------- // +// Filesystem initialization. +// ---------------------------------------------------------------------------------------- // + +enum FSInitType_t +{ + FS_INIT_FULL, // Load gameinfo.txt, maybe use filesystem_steam, and setup search paths. + FS_INIT_COMPATIBILITY_MODE // Load filesystem_stdio and that's it. +}; + +// +// Initializes qdir, and gamedir. Also initializes the VMPI filesystem if MPI is defined. +// +// pFilename can be NULL if you want to rely on vproject and qproject. If it's specified, FileSystem_Init +// will go up directories from pFilename looking for gameinfo.txt (if vproject isn't specified). +// +// If bOnlyUseFilename is true, then it won't use any alternative methods of finding the vproject dir +// (ie: it won't use -game or -vproject or the vproject env var or qproject). +// +bool FileSystem_Init( const char *pFilename, int maxMemoryUsage=0, FSInitType_t initType=FS_INIT_FULL, bool bOnlyUseFilename=false ); +void FileSystem_Term(); +bool FileSystem_SetGame( const char *szModDir ); + +CreateInterfaceFn FileSystem_GetFactory( void ); + + +extern IBaseFileSystem *g_pFileSystem; +extern IFileSystem *g_pFullFileSystem; // NOTE: this is here when VMPI is being used, but a VMPI app can + // ONLY use LoadModule/UnloadModule. + + +#endif // FILESYSTEM_TOOLS_H diff --git a/utils/common/map_shared.cpp b/utils/common/map_shared.cpp new file mode 100644 index 00000000..fc933920 --- /dev/null +++ b/utils/common/map_shared.cpp @@ -0,0 +1,133 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "map_shared.h" +#include "bsplib.h" +#include "cmdlib.h" + + +CMapError g_MapError; +int g_nMapFileVersion; + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *szKey - +// *szValue - +// *pLoadEntity - +// Output : ChunkFileResult_t +//----------------------------------------------------------------------------- +ChunkFileResult_t LoadEntityKeyCallback(const char *szKey, const char *szValue, LoadEntity_t *pLoadEntity) +{ + if (!stricmp(szKey, "classname")) + { + if (!stricmp(szValue, "func_detail")) + { + pLoadEntity->nBaseContents = CONTENTS_DETAIL; + } + else if (!stricmp(szValue, "func_ladder")) + { + pLoadEntity->nBaseContents = CONTENTS_LADDER; + } + else if (!stricmp(szValue, "func_water")) + { + pLoadEntity->nBaseContents = CONTENTS_WATER; + } + } + else if (!stricmp(szKey, "id")) + { + // UNDONE: flag entity errors by ID instead of index + //g_MapError.EntityState( atoi( szValue ) ); + return(ChunkFile_Ok); + } + else if( !stricmp( szKey, "mapversion" ) ) + { + // .vmf map revision number + g_MapRevision = atoi( szValue ); + return ( ChunkFile_Ok ); + } + + SetKeyValue( pLoadEntity->pEntity, szKey, szValue ); + + return(ChunkFile_Ok); +} + + +static ChunkFileResult_t LoadEntityCallback( CChunkFile *pFile, int nParam ) +{ + if (num_entities == MAX_MAP_ENTITIES) + { + // Exits. + g_MapError.ReportError ("num_entities == MAX_MAP_ENTITIES"); + } + + entity_t *mapent = &entities[num_entities]; + num_entities++; + memset(mapent, 0, sizeof(*mapent)); + mapent->numbrushes = 0; + + LoadEntity_t LoadEntity; + LoadEntity.pEntity = mapent; + + // No default flags/contents + LoadEntity.nBaseFlags = 0; + LoadEntity.nBaseContents = 0; + + // + // Read the entity chunk. + // + ChunkFileResult_t eResult = pFile->ReadChunk((KeyHandler_t)LoadEntityKeyCallback, &LoadEntity); + + return eResult; +} + + +bool LoadEntsFromMapFile( char const *pFilename ) +{ + // + // Dummy this up for the texture handling. This can be removed when old .MAP file + // support is removed. + // + g_nMapFileVersion = 400; + + // + // Open the file. + // + CChunkFile File; + ChunkFileResult_t eResult = File.Open( pFilename, ChunkFile_Read ); + + if(eResult == ChunkFile_Ok) + { + num_entities = 0; + + // + // Set up handlers for the subchunks that we are interested in. + // + CChunkHandlerMap Handlers; + Handlers.AddHandler("entity", (ChunkHandler_t)LoadEntityCallback, 0); + + File.PushHandlers(&Handlers); + + // + // Read the sub-chunks. We ignore keys in the root of the file. + // + while (eResult == ChunkFile_Ok) + { + eResult = File.ReadChunk(); + } + + File.PopHandlers(); + return true; + } + else + { + Error("Error in LoadEntsFromMapFile (in-memory file): %s.\n", File.GetErrorText(eResult)); + return false; + } +} + + diff --git a/utils/common/map_shared.h b/utils/common/map_shared.h new file mode 100644 index 00000000..4b0d3611 --- /dev/null +++ b/utils/common/map_shared.h @@ -0,0 +1,91 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef MAP_SHARED_H +#define MAP_SHARED_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "ChunkFile.h" +#include "bsplib.h" +#include "cmdlib.h" + + +struct LoadEntity_t +{ + entity_t *pEntity; + int nID; + int nBaseFlags; + int nBaseContents; +}; + + +class CMapError +{ +public: + + void BrushState( int brushID ) + { + m_brushID = brushID; + } + + void BrushSide( int side ) + { + m_sideIndex = side; + } + + void TextureState( const char *pTextureName ) + { + Q_strncpy( m_textureName, pTextureName, sizeof( m_textureName ) ); + } + + void ClearState( void ) + { + BrushState( 0 ); + BrushSide( 0 ); + TextureState( "Not a Parse error!" ); + } + + //----------------------------------------------------------------------------- + // Purpose: Hook the map parse errors and report brush/ent/texture state + // Input : *pErrorString - + //----------------------------------------------------------------------------- + void ReportError( const char *pErrorString ) + { + Error( "Brush %i: %s\nSide %i\nTexture: %s\n", m_brushID, pErrorString, m_sideIndex, m_textureName ); + } + + //----------------------------------------------------------------------------- + // Purpose: Hook the map parse errors and report brush/ent/texture state without exiting. + // Input : pWarningString - + //----------------------------------------------------------------------------- + void ReportWarning( const char *pWarningString ) + { + printf( "Brush %i, Side %i: %s\n", m_brushID, m_sideIndex, pWarningString ); + } + +private: + + int m_brushID; + int m_sideIndex; + char m_textureName[80]; +}; + + +extern CMapError g_MapError; +extern int g_nMapFileVersion; + + +// Shared mapload code. +ChunkFileResult_t LoadEntityKeyCallback( const char *szKey, const char *szValue, LoadEntity_t *pLoadEntity ); + +// Used by VRAD incremental lighting - only load ents from the file and +// fill in the global entities/num_entities array. +bool LoadEntsFromMapFile( char const *pFilename ); + +#endif // MAP_SHARED_H diff --git a/utils/common/movie.h b/utils/common/movie.h new file mode 100644 index 00000000..b1fc7d18 --- /dev/null +++ b/utils/common/movie.h @@ -0,0 +1,34 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#ifndef _MOVIE_H_ +#define _MOVIE_H_ + +/* + movie.h + + definitions and such for dumping screen shots to make a movie +*/ + +typedef struct +{ + unsigned long tag; + unsigned long size; +} movieblockheader_t; + + +typedef struct +{ + short width; + short height; + short depth; +} movieframe_t; + + + +#endif _MOVIE_H_ \ No newline at end of file diff --git a/utils/common/mpi_stats.cpp b/utils/common/mpi_stats.cpp new file mode 100644 index 00000000..7c4a1105 --- /dev/null +++ b/utils/common/mpi_stats.cpp @@ -0,0 +1,799 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +// Nasty headers! +#include "MySqlDatabase.h" +#include "vstdlib/strtools.h" +#include "vmpi.h" +#include "vmpi_dispatch.h" +#include "mpi_stats.h" +#include "cmdlib.h" +#include "imysqlwrapper.h" +#include "threadhelpers.h" +#include "vmpi_tools_shared.h" +#include "vstdlib/icommandline.h" + + +/* + +-- SQL code to (re)create the DB. + +-- Master generates a unique job ID (in job_master_start) and sends it to workers. +-- Each worker (and the master) make a job_worker_start, link it to the primary job ID, +-- get their own unique ID, which represents that process in that job. +-- All JobWorkerID fields link to the JobWorkerID field in job_worker_start. + +-- NOTE: do a "use vrad" or "use vvis" first, depending on the DB you want to create. + + +drop table job_master_start; +create table job_master_start ( + JobID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, index id( JobID, MachineName(5) ), + BSPFilename TINYTEXT NOT NULL, + StartTime TIMESTAMP NOT NULL, + MachineName TEXT NOT NULL, + RunningTimeMS INTEGER UNSIGNED NOT NULL, + NumWorkers INTEGER UNSIGNED NOT NULL + ); + +drop table job_master_end; +create table job_master_end ( + JobID INTEGER UNSIGNED NOT NULL, PRIMARY KEY ( JobID ), + NumWorkersConnected SMALLINT UNSIGNED NOT NULL, + NumWorkersDisconnected SMALLINT UNSIGNED NOT NULL, + ErrorText TEXT NOT NULL + ); + +drop table job_worker_start; +create table job_worker_start ( + JobWorkerID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + index index_jobid( JobID ), + index index_jobworkerid( JobWorkerID ), + + JobID INTEGER UNSIGNED NOT NULL, -- links to job_master_start::JobID + IsMaster BOOL NOT NULL, -- Set to 1 if this "worker" is the master process. + RunningTimeMS INTEGER UNSIGNED NOT NULL, + MachineName TEXT NOT NULL, + WorkerState SMALLINT UNSIGNED NOT NULL, -- 0 = disconnected, 1 = connected + NumWorkUnits INTEGER UNSIGNED NOT NULL, -- how many work units this worker has completed + CurrentStage TINYTEXT NOT NULL, -- which compile stage is it on + Thread0WU INTEGER NOT NULL, -- which WU thread 0 is on + Thread1WU INTEGER NOT NULL, -- which WU thread 1 is on + Thread2WU INTEGER NOT NULL, -- which WU thread 2 is on + Thread3WU INTEGER NOT NULL -- which WU thread 3 is on + ); + +drop table text_messages; +create table text_messages ( + JobWorkerID INTEGER UNSIGNED NOT NULL, index id( JobWorkerID, MessageIndex ), + MessageIndex INTEGER UNSIGNED NOT NULL, + Text TEXT NOT NULL + ); + +drop table graph_entry; +create table graph_entry ( + JobWorkerID INTEGER UNSIGNED NOT NULL, index id( JobWorkerID ), + MSSinceJobStart INTEGER UNSIGNED NOT NULL, + BytesSent INTEGER UNSIGNED NOT NULL, + BytesReceived INTEGER UNSIGNED NOT NULL, + WorkUnitsCompleted INTEGER UNSIGNED NOT NULL + ); + +drop table events; +create table events ( + JobWorkerID INTEGER UNSIGNED NOT NULL, index id( JobWorkerID ), + Text TEXT NOT NULL + ); +*/ + + +/* + +-- This code updates the access tables for VRAD. + +use mysql; + + +-- This updates the "user" table, which is checked when someone tries to connect to the database. +grant select,insert,update on vrad.* to vrad_worker; +grant select on vrad.* to vmpi_browser; +flush privileges; + +*/ + + +// Stats set by the app. +int g_nWorkersConnected = 0; +int g_nWorkersDisconnected = 0; + + +DWORD g_StatsStartTime; + +CMySqlDatabase *g_pDB = NULL; + +IMySQL *g_pSQL = NULL; +CSysModule *g_hMySQLDLL = NULL; + +char g_BSPFilename[256]; + +bool g_bMaster = false; +unsigned long g_JobPrimaryID = 0; // This represents this job, but doesn't link to a particular machine. +unsigned long g_JobWorkerID = 0; // A unique key in the DB that represents this machine in this job. +char g_MachineName[MAX_COMPUTERNAME_LENGTH+1] = {0}; + +unsigned long g_CurrentMessageIndex = 0; + + +HANDLE g_hPerfThread = NULL; +DWORD g_PerfThreadID = 0xFEFEFEFE; +HANDLE g_hPerfThreadExitEvent = NULL; + +// These are set by the app and they go into the database. +extern int g_ThreadWUs[4]; + +extern int VMPI_GetNumWorkUnitsCompleted( int iProc ); + + +// ---------------------------------------------------------------------------------------------------- // +// This is a helper class to build queries like the stream IO. +// ---------------------------------------------------------------------------------------------------- // + +class CMySQLQuery +{ +friend class CMySQL; + +public: + // This is like a sprintf, but it will grow the string as necessary. + void Format( const char *pFormat, ... ); + + int Execute( IMySQL *pDB ); + +private: + CUtlVector m_QueryText; +}; + + +void CMySQLQuery::Format( const char *pFormat, ... ) +{ + #define QUERYTEXT_GROWSIZE 1024 + + // This keeps growing the buffer and calling _vsnprintf until the buffer is + // large enough to hold all the data. + m_QueryText.SetSize( QUERYTEXT_GROWSIZE ); + while ( 1 ) + { + va_list marker; + va_start( marker, pFormat ); + int ret = _vsnprintf( m_QueryText.Base(), m_QueryText.Count(), pFormat, marker ); + va_end( marker ); + + if ( ret < 0 ) + { + m_QueryText.SetSize( m_QueryText.Count() + QUERYTEXT_GROWSIZE ); + } + else + { + m_QueryText[ m_QueryText.Count() - 1 ] = 0; + break; + } + } +} + + +int CMySQLQuery::Execute( IMySQL *pDB ) +{ + int ret = pDB->Execute( m_QueryText.Base() ); + m_QueryText.Purge(); + return ret; +} + + + +// ---------------------------------------------------------------------------------------------------- // +// This inserts the necessary backslashes in front of backslashes or quote characters. +// ---------------------------------------------------------------------------------------------------- // + +char* FormatStringForSQL( const char *pText ) +{ + // First, count the quotes in the string. We need to put a backslash in front of each one. + int nChars = 0; + const char *pCur = pText; + while ( *pCur != 0 ) + { + if ( *pCur == '\"' || *pCur == '\\' ) + ++nChars; + + ++pCur; + ++nChars; + } + + pCur = pText; + char *pRetVal = new char[nChars+1]; + for ( int i=0; i < nChars; ) + { + if ( *pCur == '\"' || *pCur == '\\' ) + pRetVal[i++] = '\\'; + + pRetVal[i++] = *pCur; + ++pCur; + } + pRetVal[nChars] = 0; + + return pRetVal; +} + + + +// -------------------------------------------------------------------------------- // +// Commands to add data to the database. +// -------------------------------------------------------------------------------- // +class CSQLDBCommandBase : public ISQLDBCommand +{ +public: + virtual ~CSQLDBCommandBase() + { + } + + virtual void deleteThis() + { + delete this; + } +}; + +class CSQLDBCommand_WorkerStats : public CSQLDBCommandBase +{ +public: + virtual int RunCommand() + { + int nCurConnections = VMPI_GetCurrentNumberOfConnections(); + + + // Update the NumWorkers entry. + char query[2048]; + Q_snprintf( query, sizeof( query ), "update job_master_start set NumWorkers=%d where JobID=%lu", + nCurConnections, + g_JobPrimaryID ); + g_pSQL->Execute( query ); + + + // Update the job_master_worker_stats stuff. + for ( int i=1; i < nCurConnections; i++ ) + { + unsigned long jobWorkerID = VMPI_GetJobWorkerID( i ); + + if ( jobWorkerID != 0xFFFFFFFF ) + { + Q_snprintf( query, sizeof( query ), "update " + "job_worker_start set WorkerState=%d, NumWorkUnits=%d where JobWorkerID=%lu", + VMPI_IsProcConnected( i ), + VMPI_GetNumWorkUnitsCompleted( i ), + VMPI_GetJobWorkerID( i ) + ); + g_pSQL->Execute( query ); + } + } + return 1; + } +}; + +class CSQLDBCommand_JobMasterEnd : public CSQLDBCommandBase +{ +public: + + virtual int RunCommand() + { + CMySQLQuery query; + query.Format( "insert into job_master_end values ( %lu, %d, %d, \"no errors\" )", g_JobPrimaryID, g_nWorkersConnected, g_nWorkersDisconnected ); + query.Execute( g_pSQL ); + + // Now set RunningTimeMS. + unsigned long runningTimeMS = GetTickCount() - g_StatsStartTime; + query.Format( "update job_master_start set RunningTimeMS=%lu where JobID=%lu", runningTimeMS, g_JobPrimaryID ); + query.Execute( g_pSQL ); + return 1; + } +}; + + +void UpdateJobWorkerRunningTime() +{ + unsigned long runningTimeMS = GetTickCount() - g_StatsStartTime; + + char curStage[256]; + VMPI_GetCurrentStage( curStage, sizeof( curStage ) ); + + CMySQLQuery query; + query.Format( "update job_worker_start set RunningTimeMS=%lu, CurrentStage=\"%s\", " + "Thread0WU=%d, Thread1WU=%d, Thread2WU=%d, Thread3WU=%d where JobWorkerID=%lu", + runningTimeMS, + curStage, + g_ThreadWUs[0], + g_ThreadWUs[1], + g_ThreadWUs[2], + g_ThreadWUs[3], + g_JobWorkerID ); + query.Execute( g_pSQL ); +} + + +class CSQLDBCommand_GraphEntry : public CSQLDBCommandBase +{ +public: + + CSQLDBCommand_GraphEntry( DWORD msTime, DWORD nBytesSent, DWORD nBytesReceived ) + { + m_msTime = msTime; + m_nBytesSent = nBytesSent; + m_nBytesReceived = nBytesReceived; + } + + virtual int RunCommand() + { + CMySQLQuery query; + query.Format( "insert into graph_entry (JobWorkerID, MSSinceJobStart, BytesSent, BytesReceived) " + "values ( %lu, %lu, %lu, %lu )", + g_JobWorkerID, + m_msTime, + m_nBytesSent, + m_nBytesReceived ); + + query.Execute( g_pSQL ); + + UpdateJobWorkerRunningTime(); + + ++g_CurrentMessageIndex; + return 1; + } + + DWORD m_nBytesSent; + DWORD m_nBytesReceived; + DWORD m_msTime; +}; + + + +class CSQLDBCommand_TextMessage : public CSQLDBCommandBase +{ +public: + + CSQLDBCommand_TextMessage( const char *pText ) + { + m_pText = FormatStringForSQL( pText ); + } + + virtual ~CSQLDBCommand_TextMessage() + { + delete [] m_pText; + } + + virtual int RunCommand() + { + CMySQLQuery query; + query.Format( "insert into text_messages (JobWorkerID, MessageIndex, Text) values ( %lu, %lu, \"%s\" )", g_JobWorkerID, g_CurrentMessageIndex, m_pText ); + query.Execute( g_pSQL ); + + ++g_CurrentMessageIndex; + return 1; + } + + char *m_pText; +}; + + +// -------------------------------------------------------------------------------- // +// Internal helpers. +// -------------------------------------------------------------------------------- // + +// This is the spew output before it has connected to the MySQL database. +CCriticalSection g_SpewTextCS; +CUtlVector g_SpewText( 1024 ); + + +void VMPI_Stats_SpewHook( const char *pMsg ) +{ + CCriticalSectionLock csLock( &g_SpewTextCS ); + csLock.Lock(); + + // Queue the text up so we can send it to the DB right away when we connect. + g_SpewText.AddMultipleToTail( strlen( pMsg ), pMsg ); +} + + +void PerfThread_SendSpewText() +{ + // Send the spew text to the database. + CCriticalSectionLock csLock( &g_SpewTextCS ); + csLock.Lock(); + + if ( g_SpewText.Count() > 0 ) + { + g_SpewText.AddToTail( 0 ); + g_pDB->AddCommandToQueue( new CSQLDBCommand_TextMessage( g_SpewText.Base() ), NULL ); + g_SpewText.RemoveAll(); + } + + csLock.Unlock(); +} + + +void PerfThread_AddGraphEntry( DWORD startTicks, DWORD &lastSent, DWORD &lastReceived ) +{ + // Send the graph entry with data transmission info. + DWORD curSent = g_nBytesSent + g_nMulticastBytesSent; + DWORD curReceived = g_nBytesReceived + g_nMulticastBytesReceived; + + g_pDB->AddCommandToQueue( + new CSQLDBCommand_GraphEntry( + GetTickCount() - startTicks, + curSent - lastSent, + curReceived - lastReceived ), + NULL ); + + lastSent = curSent; + lastReceived = curReceived; +} + + +// This function adds a graph_entry into the database periodically. +DWORD WINAPI PerfThreadFn( LPVOID pParameter ) +{ + DWORD lastSent = 0; + DWORD lastReceived = 0; + DWORD startTicks = GetTickCount(); + + while ( WaitForSingleObject( g_hPerfThreadExitEvent, 1000 ) != WAIT_OBJECT_0 ) + { + PerfThread_AddGraphEntry( startTicks, lastSent, lastReceived ); + + // Send updates for text output. + PerfThread_SendSpewText(); + + // If we're the master, update all the worker stats. + if ( g_bMaster ) + { + g_pDB->AddCommandToQueue( + new CSQLDBCommand_WorkerStats, + NULL ); + } + } + + // Add the remaining text and one last graph entry (which will include the current stage info). + PerfThread_SendSpewText(); + PerfThread_AddGraphEntry( startTicks, lastSent, lastReceived ); + + SetEvent( g_hPerfThreadExitEvent ); + return 0; +} + + +// -------------------------------------------------------------------------------- // +// VMPI_Stats interface. +// -------------------------------------------------------------------------------- // + +void VMPI_Stats_InstallSpewHook() +{ + InstallExtraSpewHook( VMPI_Stats_SpewHook ); +} + + +void UnloadMySQLWrapper() +{ + if ( g_hMySQLDLL ) + { + if ( g_pSQL ) + { + g_pSQL->Release(); + g_pSQL = NULL; + } + + Sys_UnloadModule( g_hMySQLDLL ); + g_hMySQLDLL = NULL; + } +} + + +bool LoadMySQLWrapper( + const char *pHostName, + const char *pDBName, + const char *pUserName + ) +{ + UnloadMySQLWrapper(); + + // Load the DLL and the interface. + if ( !Sys_LoadInterface( "mysql_wrapper", MYSQL_WRAPPER_VERSION_NAME, &g_hMySQLDLL, (void**)&g_pSQL ) ) + return false; + + // Try to init the database. + if ( !g_pSQL->InitMySQL( pDBName, pHostName, pUserName ) ) + { + UnloadMySQLWrapper(); + return false; + } + + return true; +} + + +bool VMPI_Stats_Init_Master( + const char *pHostName, + const char *pDBName, + const char *pUserName, + const char *pBSPFilename, + unsigned long *pDBJobID ) +{ + Assert( !g_pDB ); + + g_bMaster = true; + + // Connect the database. + g_pDB = new CMySqlDatabase; + if ( !g_pDB || !g_pDB->Initialize() || !LoadMySQLWrapper( pHostName, pDBName, pUserName ) ) + { + delete g_pDB; + g_pDB = NULL; + return false; + } + + DWORD size = sizeof( g_MachineName ); + GetComputerName( g_MachineName, &size ); + + // Create the job_master_start row. + Q_FileBase( pBSPFilename, g_BSPFilename, sizeof( g_BSPFilename ) ); + + g_JobPrimaryID = 0; + CMySQLQuery query; + query.Format( "insert into job_master_start ( BSPFilename, StartTime, MachineName, RunningTimeMS ) values ( \"%s\", null, \"%s\", %lu )", g_BSPFilename, g_MachineName, RUNNINGTIME_MS_SENTINEL ); + query.Execute( g_pSQL ); + + g_JobPrimaryID = g_pSQL->InsertID(); + if ( g_JobPrimaryID == 0 ) + { + delete g_pDB; + g_pDB = NULL; + return false; + } + + + // Now init the worker portion. + *pDBJobID = g_JobPrimaryID; + return VMPI_Stats_Init_Worker( NULL, NULL, NULL, g_JobPrimaryID ); +} + + + +bool VMPI_Stats_Init_Worker( const char *pHostName, const char *pDBName, const char *pUserName, unsigned long DBJobID ) +{ + g_StatsStartTime = GetTickCount(); + + // If pDBServerName is null, then we're the master and we just want to make the job_worker_start entry. + if ( pHostName ) + { + Assert( !g_pDB ); + + // Connect the database. + g_pDB = new CMySqlDatabase; + if ( !g_pDB || !g_pDB->Initialize() || !LoadMySQLWrapper( pHostName, pDBName, pUserName ) ) + { + delete g_pDB; + g_pDB = NULL; + return false; + } + + // Get our machine name to store in the database. + DWORD size = sizeof( g_MachineName ); + GetComputerName( g_MachineName, &size ); + } + + + g_JobPrimaryID = DBJobID; + g_JobWorkerID = 0; + + CMySQLQuery query; + query.Format( "insert into job_worker_start ( JobID, IsMaster, MachineName ) values ( %lu, %d, \"%s\" )", + g_JobPrimaryID, g_bMaster, g_MachineName ); + query.Execute( g_pSQL ); + + g_JobWorkerID = g_pSQL->InsertID(); + if ( g_JobWorkerID == 0 ) + { + delete g_pDB; + g_pDB = NULL; + return false; + } + + // Now create a thread that samples perf data and stores it in the database. + g_hPerfThreadExitEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); + g_hPerfThread = CreateThread( + NULL, + 0, + PerfThreadFn, + NULL, + 0, + &g_PerfThreadID ); + + return true; +} + + +void VMPI_Stats_Term() +{ + if ( !g_pDB ) + return; + + // Stop the thread. + SetEvent( g_hPerfThreadExitEvent ); + WaitForSingleObject( g_hPerfThread, INFINITE ); + + CloseHandle( g_hPerfThreadExitEvent ); + g_hPerfThreadExitEvent = NULL; + + CloseHandle( g_hPerfThread ); + g_hPerfThread = NULL; + + if ( g_bMaster ) + { + // (Write a job_master_end entry here). + g_pDB->AddCommandToQueue( new CSQLDBCommand_JobMasterEnd, NULL ); + } + + // Wait for up to a second for the DB to finish writing its data. + DWORD startTime = GetTickCount(); + while ( GetTickCount() - startTime < 1000 ) + { + if ( g_pDB->QueriesInOutQueue() == 0 ) + break; + } + + delete g_pDB; + g_pDB = NULL; + + UnloadMySQLWrapper(); +} + + +static bool ReadStringFromFile( FILE *fp, char *pStr, int strSize ) +{ + int i = 0; + for ( i=0; i < strSize-2; i++ ) + { + if ( fread( &pStr[i], 1, 1, fp ) != 1 || + pStr[i] == '\n' ) + { + break; + } + } + + pStr[i] = 0; + return i != 0; +} + + +// This looks for pDBInfoFilename in the same path as pBaseExeFilename. +// The file has 3 lines: machine name (with database), database name, username +void GetDBInfo( const char *pDBInfoFilename, CDBInfo *pInfo ) +{ + char baseExeFilename[512]; + if ( !GetModuleFileName( GetModuleHandle( NULL ), baseExeFilename, sizeof( baseExeFilename ) ) ) + Error( "GetModuleFileName failed." ); + + // Look for the info file in the same directory as the exe. + char dbInfoFilename[512]; + Q_strncpy( dbInfoFilename, baseExeFilename, sizeof( dbInfoFilename ) ); + Q_StripFilename( dbInfoFilename ); + + if ( dbInfoFilename[0] == 0 ) + Q_strncpy( dbInfoFilename, ".", sizeof( dbInfoFilename ) ); + + Q_strncat( dbInfoFilename, "/", sizeof( dbInfoFilename ), COPY_ALL_CHARACTERS ); + Q_strncat( dbInfoFilename, pDBInfoFilename, sizeof( dbInfoFilename ), COPY_ALL_CHARACTERS ); + + FILE *fp = fopen( dbInfoFilename, "rt" ); + if ( !fp ) + { + Error( "Can't open %s for database info.\n", dbInfoFilename ); + } + + if ( !ReadStringFromFile( fp, pInfo->m_HostName, sizeof( pInfo->m_HostName ) ) || + !ReadStringFromFile( fp, pInfo->m_DBName, sizeof( pInfo->m_DBName ) ) || + !ReadStringFromFile( fp, pInfo->m_UserName, sizeof( pInfo->m_UserName ) ) + ) + { + Error( "%s is not a valid database info file.\n", dbInfoFilename ); + } + + fclose( fp ); +} + + +void RunJobWatchApp( char *pCmdLine ) +{ + STARTUPINFO si; + memset( &si, 0, sizeof( si ) ); + si.cb = sizeof( si ); + + PROCESS_INFORMATION pi; + memset( &pi, 0, sizeof( pi ) ); + + if ( !CreateProcess( + NULL, + pCmdLine, + NULL, // security + NULL, + TRUE, + 0, // flags + NULL, // environment + NULL, // current directory + &si, + &pi ) ) + { + Warning( "-mpi_job_watch - error launching '%s'\n", pCmdLine ); + } +} + + +void StatsDB_InitStatsDatabase( + int argc, + char **argv, + const char *pDBInfoFilename ) +{ + unsigned long jobPrimaryID; + + // Now open the DB. + if ( g_bMPIMaster ) + { + CDBInfo dbInfo; + GetDBInfo( pDBInfoFilename, &dbInfo ); + + if ( !VMPI_Stats_Init_Master( dbInfo.m_HostName, dbInfo.m_DBName, dbInfo.m_UserName, argv[argc-1], &jobPrimaryID ) ) + { + Warning( "VMPI_Stats_Init_Master( %s, %s, %s ) failed.\n", dbInfo.m_HostName, dbInfo.m_DBName, dbInfo.m_UserName ); + + // Tell the workers not to use stats. + dbInfo.m_HostName[0] = 0; + } + + char cmdLine[2048]; + Q_snprintf( cmdLine, sizeof( cmdLine ), "vmpi_job_watch -JobID %d", jobPrimaryID ); + + Msg( "\nTo watch this job, run this command line:\n%s\n\n", cmdLine ); + + if ( CommandLine()->FindParm( "-mpi_job_watch" ) ) + { + // Convenience thing to automatically launch the job watch for this job. + RunJobWatchApp( cmdLine ); + } + + // Send the database info to all the workers. + SendDBInfo( &dbInfo, jobPrimaryID ); + } + else + { + // Wait to get DB info so we can connect to the MySQL database. + CDBInfo dbInfo; + unsigned long jobPrimaryID; + RecvDBInfo( &dbInfo, &jobPrimaryID ); + + if ( dbInfo.m_HostName[0] != 0 ) + { + if ( !VMPI_Stats_Init_Worker( dbInfo.m_HostName, dbInfo.m_DBName, dbInfo.m_UserName, jobPrimaryID ) ) + Error( "VMPI_Stats_Init_Worker( %s, %s, %d ) failed.\n", dbInfo.m_HostName, dbInfo.m_DBName, dbInfo.m_UserName, jobPrimaryID ); + } + } +} + + +unsigned long StatsDB_GetUniqueJobID() +{ + return g_JobPrimaryID; +} + + +unsigned long VMPI_Stats_GetJobWorkerID() +{ + return g_JobWorkerID; +} \ No newline at end of file diff --git a/utils/common/mpi_stats.h b/utils/common/mpi_stats.h new file mode 100644 index 00000000..c0f26194 --- /dev/null +++ b/utils/common/mpi_stats.h @@ -0,0 +1,59 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef MPI_STATS_H +#define MPI_STATS_H +#ifdef _WIN32 +#pragma once +#endif + + +// The VMPI stats module reports a bunch of statistics to a MySQL server, and the +// stats can be used to trace and graph a compile session. +// + +// Call this as soon as possible to initialize spew hooks. +void VMPI_Stats_InstallSpewHook(); + +// +// pDBServerName is the hostname (or dotted IP address) of the MySQL server to connect to. +// pBSPFilename is the last argument on the command line. +// pMachineIP is the dotted IP address of this machine. +// jobID is an 8-byte unique identifier for this job. +// +bool VMPI_Stats_Init_Master( const char *pHostName, const char *pDBName, const char *pUserName, const char *pBSPFilename, unsigned long *pDBJobID ); +bool VMPI_Stats_Init_Worker( const char *pHostName, const char *pDBName, const char *pUserName, unsigned long DBJobID ); +void VMPI_Stats_Term(); + +// Add a generic text event to the database. +void VMPI_Stats_AddEventText( const char *pText ); + +class CDBInfo +{ +public: + char m_HostName[128]; + char m_DBName[128]; + char m_UserName[128]; +}; + +// If you're the master, this loads pDBInfoFilename, sends that info to the workers, and +// connects to the database. +// +// If you're a worker, this waits for the DB info, then connects to the database. +void StatsDB_InitStatsDatabase( + int argc, + char **argv, + const char *pDBInfoFilename ); + +// The database gives back a unique ID for the job. +unsigned long StatsDB_GetUniqueJobID(); + +// Get the worker ID (used for the JobWorkerID fields in the database). +unsigned long VMPI_Stats_GetJobWorkerID(); + + +#endif // MPI_STATS_H diff --git a/utils/common/mstristrip.cpp b/utils/common/mstristrip.cpp new file mode 100644 index 00000000..54c46acb --- /dev/null +++ b/utils/common/mstristrip.cpp @@ -0,0 +1,928 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +//----------------------------------------------------------------------------- +// FILE: TRISTRIP.CPP +// +// Desc: Xbox tristripper +// +// Copyright (c) 1999-2000 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- + +// identifier was truncated to '255' characters in the debug information +#pragma warning(disable: 4786) +// conversion from 'double' to 'float' +#pragma warning(disable: 4244) +#pragma warning(disable: 4530) + +#include +#include +#include +#include +#include + +#include +#ifdef _DEBUG +#include +#endif + +#include "mstristrip.h" + +using namespace std; + +//========================================================================= +// structs +//========================================================================= +typedef vector STRIPVERTS; +typedef list STRIPLIST; +typedef WORD (*TRIANGLELIST)[3]; + +struct TRIANGLEINFO +{ + int neighbortri[3]; + int neighboredge[3]; +}; + +// return true if strip starts clockwise +inline bool FIsStripCW(const STRIPVERTS &stripvertices) +{ + // last index should have cw/ccw bool + return !!stripvertices[stripvertices.size() - 1]; +} + +// return length of strip +inline int StripLen(const STRIPVERTS &stripvertices) +{ + return stripvertices.size() - 1; +} + +// free all stripverts and clear the striplist +inline void FreeStripListVerts(STRIPLIST *pstriplist) +{ + STRIPLIST::iterator istriplist = pstriplist->begin(); + while(istriplist != pstriplist->end()) + { + STRIPVERTS *pstripverts = *istriplist; + delete pstripverts; + pstriplist->erase(istriplist++); + } +} + +//========================================================================= +// main stripper class +//========================================================================= +class CStripper +{ +public: + // ctors/dtors + CStripper(int numtris, TRIANGLELIST ptriangles); + ~CStripper(); + + // initialize tri info + void InitTriangleInfo(int tri, int vert); + + // get maximum length strip from tri/vert + int CreateStrip(int tri, int vert, int maxlen, int *pswaps, + bool flookahead, bool fstartcw, int *pstriptris, int *pstripverts); + + // stripify entire mesh + void BuildStrips(STRIPLIST *pstriplist, int maxlen, bool flookahead); + + // blast strip indices to ppstripindices + int CreateManyStrips(STRIPLIST *pstriplist, WORD **ppstripindices); + int CreateLongStrip(STRIPLIST *pstriplist, WORD **ppstripindices); + + inline int GetNeighborCount(int tri) + { + int count = 0; + for(int vert = 0; vert < 3; vert++) + { + int neighbortri = m_ptriinfo[tri].neighbortri[vert]; + count += (neighbortri != -1) && !m_pused[neighbortri]; + } + return count; + } + + // from callee + int m_numtris; // # tris + TRIANGLELIST m_ptriangles; // trilist + + TRIANGLEINFO *m_ptriinfo; // tri edge, neighbor info + int *m_pused; // tri used flag +}; + +//========================================================================= +// vertex cache class +//========================================================================= +class CVertCache +{ +public: + CVertCache() + { Reset(); } + ~CVertCache() + {}; + + // reset cache + void Reset() + { + m_iCachePtr = 0; + m_cachehits = 0; + memset(m_rgCache, 0xff, sizeof(m_rgCache)); + } + + // add vertindex to cache + bool Add(int strip, int vertindex); + + int NumCacheHits() const + { return m_cachehits; } + +// enum { CACHE_SIZE = 10 }; + enum { CACHE_SIZE = 18 }; + +private: + int m_cachehits; // current # of cache hits + WORD m_rgCache[CACHE_SIZE]; // vertex cache + int m_rgCacheStrip[CACHE_SIZE]; // strip # which added vert + int m_iCachePtr; // fifo ptr +}; + +//========================================================================= +// Get maximum length of strip starting at tri/vert +//========================================================================= +int CStripper::CreateStrip(int tri, int vert, int maxlen, int *pswaps, + bool flookahead, bool fstartcw, int *pstriptris, int *pstripverts) +{ + *pswaps = 0; + + // this guy has already been used? + if(m_pused[tri]) + return 0; + + // mark tri as used + m_pused[tri] = 1; + + int swaps = 0; + + // add first tri info + pstriptris[0] = tri; + pstriptris[1] = tri; + pstriptris[2] = tri; + + if(fstartcw) + { + pstripverts[0] = (vert) % 3; + pstripverts[1] = (vert + 1) % 3; + pstripverts[2] = (vert + 2) % 3; + } + else + { + pstripverts[0] = (vert + 1) % 3; + pstripverts[1] = (vert + 0) % 3; + pstripverts[2] = (vert + 2) % 3; + } + fstartcw = !fstartcw; + + // get next tri information + int edge = (fstartcw ? vert + 2 : vert + 1) % 3; + int nexttri = m_ptriinfo[tri].neighbortri[edge]; + int nextvert = m_ptriinfo[tri].neighboredge[edge]; + + // start building the strip until we run out of room or indices + int stripcount; + for( stripcount = 3; stripcount < maxlen; stripcount++) + { + // dead end? + if(nexttri == -1 || m_pused[nexttri]) + break; + + // move to next tri + tri = nexttri; + vert = nextvert; + + // toggle orientation + fstartcw = !fstartcw; + + // find the next natural edge + int edge = (fstartcw ? vert + 2 : vert + 1) % 3; + nexttri = m_ptriinfo[tri].neighbortri[edge]; + nextvert = m_ptriinfo[tri].neighboredge[edge]; + + bool fswap = false; + if(nexttri == -1 || m_pused[nexttri]) + { + // if the next tri is a dead end - try swapping orientation + fswap = true; + } + else if(flookahead) + { + // try a swap and see who our new neighbor would be + int edgeswap = (fstartcw ? vert + 1 : vert + 2) % 3; + int nexttriswap = m_ptriinfo[tri].neighbortri[edgeswap]; + int nextvertswap = m_ptriinfo[tri].neighboredge[edgeswap]; + + if(nexttriswap != -1 && !m_pused[nexttriswap]) + { + assert(nexttri != -1); + + // if the swap neighbor has a lower count, change directions + if(GetNeighborCount(nexttriswap) < GetNeighborCount(nexttri)) + { + fswap = true; + } + else if(GetNeighborCount(nexttriswap) == GetNeighborCount(nexttri)) + { + // if they have the same number of neighbors - check their neighbors + edgeswap = (fstartcw ? nextvertswap + 2 : nextvertswap + 1) % 3; + nexttriswap = m_ptriinfo[nexttriswap].neighbortri[edgeswap]; + + int edge1 = (fstartcw ? nextvert + 1 : nextvert + 2) % 3; + int nexttri1 = m_ptriinfo[nexttri].neighbortri[edge1]; + + if(nexttri1 == -1 || m_pused[nexttri1]) + { + // natural winding order leads us to a dead end so turn + fswap = true; + } + else if(nexttriswap != -1 && !m_pused[nexttriswap]) + { + // check neighbor counts on both directions and swap if it's better + if(GetNeighborCount(nexttriswap) < GetNeighborCount(nexttri1)) + fswap = true; + } + } + } + } + + if(fswap) + { + // we've been told to change directions so make sure we actually can + // and then add the swap vertex + int edgeswap = (fstartcw ? vert + 1 : vert + 2) % 3; + nexttri = m_ptriinfo[tri].neighbortri[edgeswap]; + nextvert = m_ptriinfo[tri].neighboredge[edgeswap]; + + if(nexttri != -1 && !m_pused[nexttri]) + { + pstriptris[stripcount] = pstriptris[stripcount - 2]; + pstripverts[stripcount] = pstripverts[stripcount - 2]; + stripcount++; + swaps++; + fstartcw = !fstartcw; + } + } + + // record index information + pstriptris[stripcount] = tri; + pstripverts[stripcount] = (vert + 2) % 3; + + // mark triangle as used + m_pused[tri] = 1; + } + + // clear the used flags + for(int j = 2; j < stripcount; j++) + m_pused[pstriptris[j]] = 0; + + // return swap count and striplen + *pswaps = swaps; + return stripcount; +} + +//========================================================================= +// Given a striplist and current cache state, pick the best next strip +//========================================================================= +STRIPLIST::iterator FindBestCachedStrip(STRIPLIST *pstriplist, + const CVertCache &vertcachestate) +{ + bool fFlipStrip = false; + int maxcachehits = -1; + STRIPLIST::iterator istriplistbest = pstriplist->begin(); + + int striplen = StripLen(**istriplistbest); + bool fstartcw = FIsStripCW(**istriplistbest); + + // go through all the other strips looking for the best caching + for(STRIPLIST::iterator istriplist = pstriplist->begin(); + istriplist != pstriplist->end(); + ++istriplist) + { + bool fFlip = false; + const STRIPVERTS &stripverts = **istriplist; + int striplennew = StripLen(stripverts); + + // check cache if this strip is the same type as us (ie: cw/odd) + if((FIsStripCW(stripverts) == fstartcw) && + ((striplen & 0x1) == (striplennew & 0x1))) + { + // copy current state of cache + CVertCache vertcachenew = vertcachestate; + + // figure out what this guy would do to our cache + for(int ivert = 0; ivert < striplennew; ivert++) + vertcachenew.Add(2, stripverts[ivert]); + + // even length strip - see if better cache hits reversed + if(!(striplennew & 0x1)) + { + CVertCache vertcacheflipped = vertcachestate; + + for(int ivert = StripLen(stripverts) - 1; ivert >= 0; ivert--) + vertcacheflipped.Add(2, stripverts[ivert]); + + if(vertcacheflipped.NumCacheHits() > vertcachenew.NumCacheHits()) + { + vertcachenew = vertcacheflipped; + fFlip = true; + } + } + + // record the best number of cache hits to date + int numcachehits = vertcachenew.NumCacheHits() - vertcachestate.NumCacheHits(); + if(numcachehits > maxcachehits) + { + maxcachehits = numcachehits; + istriplistbest = istriplist; + fFlipStrip = fFlip; + } + } + } + + if(fFlipStrip) + { + STRIPVERTS &stripverts = **istriplistbest; + STRIPVERTS::iterator vend = stripverts.end(); + + reverse(stripverts.begin(), --vend); + } + + // make sure we keep the list in order and always pull off + // the first dude. + if(istriplistbest != pstriplist->begin()) + swap(*istriplistbest, *pstriplist->begin()); + + return pstriplist->begin(); +} + + +//========================================================================= +// Don't merge the strips - just blast em into the stripbuffer one by one +// (useful for debugging) +//========================================================================= +int CStripper::CreateManyStrips(STRIPLIST *pstriplist, WORD **ppstripindices) +{ + // allow room for each of the strips size plus the final 0 + int indexcount = pstriplist->size() + 1; + + // we're storing the strips in [size1 i1 i2 i3][size2 i4 i5 i6][0] format + STRIPLIST::iterator istriplist; + for( istriplist = pstriplist->begin(); istriplist != pstriplist->end(); ++istriplist) + { + // add striplength plus potential degenerate to swap ccw --> cw + indexcount += StripLen(**istriplist) + 1; + } + + // alloc the space for all this stuff + WORD *pstripindices = new WORD [indexcount]; + assert(pstripindices); + + CVertCache vertcache; + int numstripindices = 0; + + for(istriplist = pstriplist->begin(); + !pstriplist->empty(); + istriplist = FindBestCachedStrip(pstriplist, vertcache)) + { + const STRIPVERTS &stripverts = **istriplist; + + if(!FIsStripCW(stripverts)) + { + // add an extra index if it's ccw + pstripindices[numstripindices++] = StripLen(stripverts) + 1; + pstripindices[numstripindices++] = stripverts[0]; + } + else + { + // add the strip length + pstripindices[numstripindices++] = StripLen(stripverts); + } + + // add all the strip indices + for(int i = 0; i < StripLen(stripverts); i++) + { + pstripindices[numstripindices++] = stripverts[i]; + vertcache.Add(1, stripverts[i]); + } + + // free this guy and pop him off the list + delete &stripverts; + pstriplist->pop_front(); + } + + // add terminating zero + pstripindices[numstripindices++] = 0; + *ppstripindices = pstripindices; + + return numstripindices; +} + +//========================================================================= +// Merge striplist into one big uberlist with (hopefully) optimal caching +//========================================================================= +int CStripper::CreateLongStrip(STRIPLIST *pstriplist, WORD **ppstripindices) +{ + // allow room for one strip length plus a possible 3 extra indices per + // concatenated strip list plus the final 0 + int indexcount = (pstriplist->size() * 3) + 2; + + // we're storing the strips in [size1 i1 i2 i3][size2 i4 i5 i6][0] format + STRIPLIST::iterator istriplist; + for( istriplist = pstriplist->begin(); istriplist != pstriplist->end(); ++istriplist) + { + indexcount += StripLen(**istriplist); + } + + // alloc the space for all this stuff + WORD *pstripindices = new WORD [indexcount]; + assert(pstripindices); + + CVertCache vertcache; + int numstripindices = 0; + + // add first strip + istriplist = pstriplist->begin(); + const STRIPVERTS &stripverts = **istriplist; + + // first strip should be cw + assert(FIsStripCW(stripverts)); + + for(int ivert = 0; ivert < StripLen(stripverts); ivert++) + { + pstripindices[numstripindices++] = stripverts[ivert]; + vertcache.Add(1, stripverts[ivert]); + } + + // kill first dude + delete &stripverts; + pstriplist->erase(istriplist); + + // add all the others + while(pstriplist->size()) + { + istriplist = FindBestCachedStrip(pstriplist, vertcache); + STRIPVERTS &stripverts = **istriplist; + short lastvert = pstripindices[numstripindices - 1]; + short firstvert = stripverts[0]; + + if(firstvert != lastvert) + { + // add degenerate from last strip + pstripindices[numstripindices++] = lastvert; + + // add degenerate from our strip + pstripindices[numstripindices++] = firstvert; + } + + // if we're not orientated correctly, we need to add a degenerate + if(FIsStripCW(stripverts) != !(numstripindices & 0x1)) + { + // This shouldn't happen - we're currently trying very hard + // to keep everything oriented correctly. + assert(false); + pstripindices[numstripindices++] = firstvert; + } + + // add these verts + for(int ivert = 0; ivert < StripLen(stripverts); ivert++) + { + pstripindices[numstripindices++] = stripverts[ivert]; + vertcache.Add(1, stripverts[ivert]); + } + + // free these guys + delete &stripverts; + pstriplist->erase(istriplist); + } + + *ppstripindices = pstripindices; + return numstripindices; +} + +//========================================================================= +// Build a (hopefully) optimal set of strips from a trilist +//========================================================================= +void CStripper::BuildStrips(STRIPLIST *pstriplist, int maxlen, bool flookahead) +{ + // temp indices storage + const int ctmpverts = 1024; + int pstripverts[ctmpverts + 1]; + int pstriptris[ctmpverts + 1]; + + assert(maxlen <= ctmpverts); + + // clear all the used flags for the tris + memset(m_pused, 0, sizeof(m_pused[0]) * m_numtris); + + bool fstartcw = true; + for(;;) + { + int besttri; + int bestvert; + float bestratio = 2.0f; + int bestneighborcount = INT_MAX; + + int tri; + for( tri = 0; tri < m_numtris; tri++) + { + // if used the continue + if(m_pused[tri]) + continue; + + // get the neighbor count + int curneightborcount = GetNeighborCount(tri); + assert(curneightborcount >= 0 && curneightborcount <= 3); + + // push all the singletons to the very end + if(!curneightborcount) + curneightborcount = 4; + + // if this guy has more neighbors than the current best - bail + if(curneightborcount > bestneighborcount) + continue; + + // try starting the strip with each of this tris verts + for(int vert = 0; vert < 3; vert++) + { + int swaps; + int len = CreateStrip(tri, vert, maxlen, &swaps, flookahead, + fstartcw, pstriptris, pstripverts); + assert(len); + + int striplen = len - swaps; + float ratio = (len == 3) ? 1.0f : (float)swaps / len; + + // check if this ratio is better than what we've already got for + // this neighborcount + if((curneightborcount < bestneighborcount) || + ((curneightborcount == bestneighborcount) && (ratio < bestratio))) + { + bestneighborcount = curneightborcount; + + besttri = tri; + bestvert = vert; + bestratio = ratio; + } + + } + } + + // no strips found? + if(bestneighborcount == INT_MAX) + break; + + // recreate this strip + int swaps; + int len = CreateStrip(besttri, bestvert, maxlen, + &swaps, flookahead, fstartcw, pstriptris, pstripverts); + assert(len); + + // mark the tris on the best strip as used + for(tri = 0; tri < len; tri++) + m_pused[pstriptris[tri]] = 1; + + // create a new STRIPVERTS and stuff in the indices + STRIPVERTS *pstripvertices = new STRIPVERTS(len + 1); + assert(pstripvertices); + + // store orientation in first entry + for(tri = 0; tri < len; tri++) + (*pstripvertices)[tri] = m_ptriangles[pstriptris[tri]][pstripverts[tri]]; + (*pstripvertices)[len] = fstartcw; + + // store the STRIPVERTS + pstriplist->push_back(pstripvertices); + + // if strip was odd - swap orientation + if((len & 0x1)) + fstartcw = !fstartcw; + } + +#ifdef _DEBUG + // make sure all tris are used + for(int t = 0; t < m_numtris; t++) + assert(m_pused[t]); +#endif +} + +//========================================================================= +// Guesstimate on the total index count for this list of strips +//========================================================================= +int EstimateStripCost(STRIPLIST *pstriplist) +{ + int count = 0; + + for(STRIPLIST::iterator istriplist = pstriplist->begin(); + istriplist != pstriplist->end(); + ++istriplist) + { + // add count of indices + count += StripLen(**istriplist); + } + + // assume 2 indices per strip to tack all these guys together + return count + (pstriplist->size() - 1) * 2; +} + +//========================================================================= +// Initialize triangle information (edges, #neighbors, etc.) +//========================================================================= +void CStripper::InitTriangleInfo(int tri, int vert) +{ + WORD *ptriverts = &m_ptriangles[tri + 1][0]; + int vert1 = m_ptriangles[tri][(vert + 1) % 3]; + int vert2 = m_ptriangles[tri][vert]; + + for(int itri = tri + 1; itri < m_numtris; itri++, ptriverts += 3) + { + if(m_pused[itri] != 0x7) + { + for(int ivert = 0; ivert < 3; ivert++) + { + if((ptriverts[ivert] == vert1) && + (ptriverts[(ivert + 1) % 3] == vert2)) + { + // add the triangle info + m_ptriinfo[tri].neighbortri[vert] = itri; + m_ptriinfo[tri].neighboredge[vert] = ivert; + m_pused[tri] |= (1 << vert); + + m_ptriinfo[itri].neighbortri[ivert] = tri; + m_ptriinfo[itri].neighboredge[ivert] = vert; + m_pused[itri] |= (1 << ivert); + return; + } + } + } + } +} + +//========================================================================= +// CStripper ctor +//========================================================================= +CStripper::CStripper(int numtris, TRIANGLELIST ptriangles) +{ + // store trilist info + m_numtris = numtris; + m_ptriangles = ptriangles; + + m_pused = new int[numtris]; + assert(m_pused); + m_ptriinfo = new TRIANGLEINFO[numtris]; + assert(m_ptriinfo); + + // init triinfo + int itri; + for( itri = 0; itri < numtris; itri++) + { + m_ptriinfo[itri].neighbortri[0] = -1; + m_ptriinfo[itri].neighbortri[1] = -1; + m_ptriinfo[itri].neighbortri[2] = -1; + } + + // clear the used flag + memset(m_pused, 0, sizeof(m_pused[0]) * m_numtris); + + // go through all the triangles and find edges, neighbor counts + for(itri = 0; itri < numtris; itri++) + { + for(int ivert = 0; ivert < 3; ivert++) + { + if(!(m_pused[itri] & (1 << ivert))) + InitTriangleInfo(itri, ivert); + } + } + + // clear the used flags from InitTriangleInfo + memset(m_pused, 0, sizeof(m_pused[0]) * m_numtris); +} + +//========================================================================= +// CStripper dtor +//========================================================================= +CStripper::~CStripper() +{ + // free stuff + delete [] m_pused; + m_pused = NULL; + + delete [] m_ptriinfo; + m_ptriinfo = NULL; +} + +//========================================================================= +// Add an index to the cache - returns true if it was added, false otherwise +//========================================================================= +bool CVertCache::Add(int strip, int vertindex) +{ + // find index in cache + for(int iCache = 0; iCache < CACHE_SIZE; iCache++) + { + if(vertindex == m_rgCache[iCache]) + { + // if it's in the cache and it's from a different strip + // change the strip to the new one and count the cache hit + if(strip != m_rgCacheStrip[iCache]) + { + m_cachehits++; + m_rgCacheStrip[iCache] = strip; + return true; + } + + // we added this item to the cache earlier - carry on + return false; + } + } + + // not in cache, add vert and strip + m_rgCache[m_iCachePtr] = vertindex; + m_rgCacheStrip[m_iCachePtr] = strip; + m_iCachePtr = (m_iCachePtr + 1) % CACHE_SIZE; + return true; +} + +#ifdef _DEBUG +//========================================================================= +// Turn on c runtime leak checking, etc. +//========================================================================= +void EnableLeakChecking() +{ + int flCrtDbgFlags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + + flCrtDbgFlags &= + ~(_CRTDBG_LEAK_CHECK_DF | + _CRTDBG_CHECK_ALWAYS_DF | + _CRTDBG_DELAY_FREE_MEM_DF); + + // always check for memory leaks + flCrtDbgFlags |= _CRTDBG_LEAK_CHECK_DF; + + // others you may / may not want to set + flCrtDbgFlags |= _CRTDBG_CHECK_ALWAYS_DF; + flCrtDbgFlags |= _CRTDBG_DELAY_FREE_MEM_DF; + + _CrtSetDbgFlag(flCrtDbgFlags); + + // all types of reports go via OutputDebugString + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); + + // big errors and asserts get their own assert window + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_WNDW); + + // _CrtSetBreakAlloc(0); +} +#endif + +//========================================================================= +// Main Stripify routine +//========================================================================= +int Stripify(int numtris, WORD *ptriangles, int *pnumindices, WORD **ppstripindices) +{ + if(!numtris || !ptriangles) + return 0; + +#ifdef _DEBUG +// EnableLeakChecking(); +#endif + + CStripper stripper(numtris, (TRIANGLELIST)ptriangles); + + // map of various args to try stripifying mesh with + struct ARGMAP + { + int maxlen; // maximum length of strips + bool flookahead; // use sgi greedy lookahead (or not) + } rgargmap[] = + { + { 1024, true }, + { 1024, false }, + }; + static const int cargmaps = sizeof(rgargmap) / sizeof(rgargmap[0]); + STRIPLIST striplistbest; + int bestlistcost = 0; + + for(int imap = 0; imap < cargmaps; imap++) + { + STRIPLIST striplist; + + // build the strip with the various args + stripper.BuildStrips(&striplist, rgargmap[imap].maxlen, + rgargmap[imap].flookahead); + + // guesstimate the list cost and store it if it's good + int listcost = EstimateStripCost(&striplist); + if(!bestlistcost || (listcost < bestlistcost)) + { + // free the old best list + FreeStripListVerts(&striplistbest); + + // store the new best list + striplistbest = striplist; + bestlistcost = listcost; + assert(bestlistcost > 0); + } + else + { + FreeStripListVerts(&striplist); + } + } + +#ifdef NEVER + // Return the strips in [size1 i1 i2 i3][size2 i4 i5 i6]...[0] format + // Very useful for debugging... + return stripper.CreateManyStrips(&striplistbest, ppstripindices); +#endif // NEVER + + // return one big long strip + int numindices = stripper.CreateLongStrip(&striplistbest, ppstripindices); + + if(pnumindices) + *pnumindices = numindices; + return numindices; +} + +//========================================================================= +// Class used to vertices for locality of access. +//========================================================================= +struct SortEntry +{ +public: + int iFirstUsed; + int iOrigIndex; + + bool operator<(const SortEntry& rhs) + { + return iFirstUsed < rhs.iFirstUsed; + } +}; + +//========================================================================= +// Reorder the vertices +//========================================================================= +void ComputeVertexPermutation(int numstripindices, WORD* pstripindices, + int* pnumverts, WORD** ppvertexpermutation) +{ + // Sort verts to maximize locality. + SortEntry* pSortTable = new SortEntry[*pnumverts]; + + // Fill in original index. + int i; + for( i = 0; i < *pnumverts; i++) + { + pSortTable[i].iOrigIndex = i; + pSortTable[i].iFirstUsed = -1; + } + + // Fill in first used flag. + for(i = 0; i < numstripindices; i++) + { + int index = pstripindices[i]; + + if(pSortTable[index].iFirstUsed == -1) + pSortTable[index].iFirstUsed = i; + } + + // Sort the table. + sort(pSortTable, pSortTable + *pnumverts); + + // Copy re-mapped to orignal vertex permutaion into output array. + *ppvertexpermutation = new WORD[*pnumverts]; + + for(i = 0; i < *pnumverts; i++) + { + (*ppvertexpermutation)[i] = pSortTable[i].iOrigIndex; + } + + // Build original to re-mapped permutation. + WORD* pInversePermutation = new WORD[numstripindices]; + + for(i = 0; i < *pnumverts; i++) + { + pInversePermutation[pSortTable[i].iOrigIndex] = i; + } + + // We need to remap indices as well. + for(i = 0; i < numstripindices; i++) + { + pstripindices[i] = pInversePermutation[pstripindices[i]]; + } + + delete[] pSortTable; + delete[] pInversePermutation; +} + diff --git a/utils/common/mstristrip.h b/utils/common/mstristrip.h new file mode 100644 index 00000000..2960c716 --- /dev/null +++ b/utils/common/mstristrip.h @@ -0,0 +1,43 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +//----------------------------------------------------------------------------- +// FILE: TRISTRIP.H +// +// Desc: tristrip header file +// +// Copyright (c) 1999-2000 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- + +typedef unsigned short WORD; + +// +// Main Stripify routine. Returns number of strip indices contained +// in ppstripindices. Caller must delete [] ppstripindices. +// +int Stripify( + int numtris, // Number of triangles + WORD *ptriangles, // triangle indices pointer + int *pnumindices, // number of indices in ppstripindices (out) + WORD **ppstripindices // triangle strip indices +); + +// +// Re-arrange vertices so that they occur in the order that they are first +// used. This function doesn't actually move vertex data around, it returns +// an array that specifies where in the new vertex array each old vertex +// should go. It also re-maps the strip indices to use the new vertex +// locations. Caller must delete [] pVertexPermutation. +// +void ComputeVertexPermutation +( + int numstripindices, // Number of strip indices + WORD *pstripindices, // Strip indices + int *pnumverts, // Number of verts (in and out) + WORD **ppvertexpermutation // Map from orignal index to remapped index +); + diff --git a/utils/common/pacifier.cpp b/utils/common/pacifier.cpp new file mode 100644 index 00000000..1860943d --- /dev/null +++ b/utils/common/pacifier.cpp @@ -0,0 +1,56 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include +#include "basetypes.h" +#include "pacifier.h" +#include "tier0/dbg.h" + + +static int g_LastPacifierDrawn = -1; + + +void StartPacifier( char const *pPrefix ) +{ + Msg( "%s", pPrefix ); + g_LastPacifierDrawn = -1; + UpdatePacifier( 0.001f ); +} + +void UpdatePacifier( float flPercent ) +{ + int iCur = (int)(flPercent * 40.0f); + iCur = clamp( iCur, g_LastPacifierDrawn, 40 ); + + if( iCur != g_LastPacifierDrawn ) + { + for( int i=g_LastPacifierDrawn+1; i <= iCur; i++ ) + { + if ( !( i % 4 ) ) + { + Msg("%d", i/4); + } + else + { + if( i != 40 ) + { + Msg("."); + } + } + } + + g_LastPacifierDrawn = iCur; + } +} + +void EndPacifier( bool bCarriageReturn ) +{ + UpdatePacifier(1); + + if( bCarriageReturn ) + Msg("\n"); +} diff --git a/utils/common/pacifier.h b/utils/common/pacifier.h new file mode 100644 index 00000000..11b799d1 --- /dev/null +++ b/utils/common/pacifier.h @@ -0,0 +1,22 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef PACIFIER_H +#define PACIFIER_H +#ifdef _WIN32 +#pragma once +#endif + + +// Use these to display a pacifier like: +// ProcessBlock_Thread: 0...1...2...3...4...5...6...7...8...9... (0) +void StartPacifier( char const *pPrefix ); +void UpdatePacifier( float flPercent ); // percent value between 0 and 1. +void EndPacifier( bool bCarriageReturn=true ); + + +#endif // PACIFIER_H diff --git a/utils/common/physdll.cpp b/utils/common/physdll.cpp new file mode 100644 index 00000000..cb501be2 --- /dev/null +++ b/utils/common/physdll.cpp @@ -0,0 +1,31 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#include +#include "physdll.h" +#include "filesystem_tools.h" + +static CSysModule *pPhysicsModule = NULL; +CreateInterfaceFn GetPhysicsFactory( void ) +{ + if ( !pPhysicsModule ) + { + pPhysicsModule = g_pFullFileSystem->LoadModule( "VPHYSICS.DLL" ); + if ( !pPhysicsModule ) + return NULL; + } + + return Sys_GetFactory( pPhysicsModule ); +} + +void PhysicsDLLPath( const char *pPathname ) +{ + if ( !pPhysicsModule ) + { + pPhysicsModule = g_pFullFileSystem->LoadModule( pPathname ); + } +} diff --git a/utils/common/physdll.h b/utils/common/physdll.h new file mode 100644 index 00000000..34b9beb1 --- /dev/null +++ b/utils/common/physdll.h @@ -0,0 +1,30 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef PHYSDLL_H +#define PHYSDLL_H +#pragma once + + +#ifdef __cplusplus +#include "vphysics_interface.h" +class IPhysics; +class IPhysicsCollision; + +extern CreateInterfaceFn GetPhysicsFactory( void ); + +extern "C" { +#endif + +// tools need to force the path +void PhysicsDLLPath( const char *pPathname ); + +#ifdef __cplusplus +} +#endif + +#endif // PHYSDLL_H diff --git a/utils/common/polylib.cpp b/utils/common/polylib.cpp new file mode 100644 index 00000000..06286120 --- /dev/null +++ b/utils/common/polylib.cpp @@ -0,0 +1,915 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//=============================================================================// + +#include "cmdlib.h" +#include "mathlib.h" +#include "polylib.h" +#include "worldsize.h" +#include "threads.h" +#include "tier0/dbg.h" + +// doesn't seem to need to be here? -- in threads.h +//extern int numthreads; + +// counters are only bumped when running single threaded, +// because they are an awefull coherence problem +int c_active_windings; +int c_peak_windings; +int c_winding_allocs; +int c_winding_points; + +void pw(winding_t *w) +{ + int i; + for (i=0 ; inumpoints ; i++) + printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]); +} + +winding_t *winding_pool[MAX_POINTS_ON_WINDING+4]; + +/* +============= +AllocWinding +============= +*/ +winding_t *AllocWinding (int points) +{ + winding_t *w; + + if (numthreads == 1) + { + c_winding_allocs++; + c_winding_points += points; + c_active_windings++; + if (c_active_windings > c_peak_windings) + c_peak_windings = c_active_windings; + } + ThreadLock(); + if (winding_pool[points]) + { + w = winding_pool[points]; + winding_pool[points] = w->next; + } + else + { + w = (winding_t *)malloc(sizeof(*w)); + w->p = (Vector *)calloc( points, sizeof(Vector) ); + } + ThreadUnlock(); + w->numpoints = 0; // None are occupied yet even though allocated. + w->maxpoints = points; + w->next = NULL; + return w; +} + +void FreeWinding (winding_t *w) +{ + if (w->numpoints == 0xdeaddead) + Error ("FreeWinding: freed a freed winding"); + + ThreadLock(); + w->numpoints = 0xdeaddead; // flag as freed + w->next = winding_pool[w->maxpoints]; + winding_pool[w->maxpoints] = w; + ThreadUnlock(); +} + +/* +============ +RemoveColinearPoints +============ +*/ +int c_removed; + +void RemoveColinearPoints (winding_t *w) +{ + int i, j, k; + Vector v1, v2; + int nump; + Vector p[MAX_POINTS_ON_WINDING]; + + nump = 0; + for (i=0 ; inumpoints ; i++) + { + j = (i+1)%w->numpoints; + k = (i+w->numpoints-1)%w->numpoints; + VectorSubtract (w->p[j], w->p[i], v1); + VectorSubtract (w->p[i], w->p[k], v2); + VectorNormalize(v1); + VectorNormalize(v2); + if (DotProduct(v1, v2) < 0.999) + { + VectorCopy (w->p[i], p[nump]); + nump++; + } + } + + if (nump == w->numpoints) + return; + + if (numthreads == 1) + c_removed += w->numpoints - nump; + w->numpoints = nump; + memcpy (w->p, p, nump*sizeof(p[0])); +} + +/* +============ +WindingPlane +============ +*/ +void WindingPlane (winding_t *w, Vector &normal, vec_t *dist) +{ + Vector v1, v2; + + VectorSubtract (w->p[1], w->p[0], v1); + + // HACKHACK: Avoid potentially collinear verts + if ( w->numpoints > 3 ) + { + VectorSubtract (w->p[3], w->p[0], v2); + } + else + { + VectorSubtract (w->p[2], w->p[0], v2); + } + CrossProduct (v2, v1, normal); + VectorNormalize (normal); + *dist = DotProduct (w->p[0], normal); + +} + + +/* +============= +WindingArea +============= +*/ +vec_t WindingArea(winding_t *w) +{ + int i; + Vector d1, d2, cross; + vec_t total; + + total = 0; + for (i=2 ; inumpoints ; i++) + { + VectorSubtract (w->p[i-1], w->p[0], d1); + VectorSubtract (w->p[i], w->p[0], d2); + CrossProduct (d1, d2, cross); + total += VectorLength ( cross ); + } + return total * 0.5; +} + +void WindingBounds (winding_t *w, Vector &mins, Vector &maxs) +{ + vec_t v; + int i,j; + + mins[0] = mins[1] = mins[2] = 99999; + maxs[0] = maxs[1] = maxs[2] = -99999; + + for (i=0 ; inumpoints ; i++) + { + for (j=0 ; j<3 ; j++) + { + v = w->p[i][j]; + if (v < mins[j]) + mins[j] = v; + if (v > maxs[j]) + maxs[j] = v; + } + } +} + +/* +============= +WindingCenter +============= +*/ +void WindingCenter (winding_t *w, Vector ¢er) +{ + int i; + float scale; + + VectorCopy (vec3_origin, center); + for (i=0 ; inumpoints ; i++) + VectorAdd (w->p[i], center, center); + + scale = 1.0/w->numpoints; + VectorScale (center, scale, center); +} + + + +/* +============= +WindingCenter +============= +*/ +vec_t WindingAreaAndBalancePoint( winding_t *w, Vector ¢er ) +{ + int i; + Vector d1, d2, cross; + vec_t total; + + VectorCopy (vec3_origin, center); + if ( !w ) + return 0.0f; + + total = 0; + for (i=2 ; inumpoints ; i++) + { + VectorSubtract (w->p[i-1], w->p[0], d1); + VectorSubtract (w->p[i], w->p[0], d2); + CrossProduct (d1, d2, cross); + float area = VectorLength ( cross ); + total += area; + + // center of triangle, weighed by area + VectorMA( center, area / 3.0, w->p[i-1], center ); + VectorMA( center, area / 3.0, w->p[i], center ); + VectorMA( center, area / 3.0, w->p[0], center ); + } + if (total) + { + VectorScale( center, 1.0 / total, center ); + } + return total * 0.5; +} + +/* +================= +BaseWindingForPlane +================= +*/ +winding_t *BaseWindingForPlane (const Vector &normal, vec_t dist) +{ + int i, x; + vec_t max, v; + Vector org, vright, vup; + winding_t *w; + +// find the major axis + + max = -1; + x = -1; + for (i=0 ; i<3; i++) + { + v = fabs(normal[i]); + if (v > max) + { + x = i; + max = v; + } + } + if (x==-1) + Error ("BaseWindingForPlane: no axis found"); + + VectorCopy (vec3_origin, vup); + switch (x) + { + case 0: + case 1: + vup[2] = 1; + break; + case 2: + vup[0] = 1; + break; + } + + v = DotProduct (vup, normal); + VectorMA (vup, -v, normal, vup); + VectorNormalize (vup); + + VectorScale (normal, dist, org); + + CrossProduct (vup, normal, vright); + + VectorScale (vup, (MAX_COORD_INTEGER*4), vup); + VectorScale (vright, (MAX_COORD_INTEGER*4), vright); + +// project a really big axis aligned box onto the plane + w = AllocWinding (4); + + VectorSubtract (org, vright, w->p[0]); + VectorAdd (w->p[0], vup, w->p[0]); + + VectorAdd (org, vright, w->p[1]); + VectorAdd (w->p[1], vup, w->p[1]); + + VectorAdd (org, vright, w->p[2]); + VectorSubtract (w->p[2], vup, w->p[2]); + + VectorSubtract (org, vright, w->p[3]); + VectorSubtract (w->p[3], vup, w->p[3]); + + w->numpoints = 4; + + return w; +} + +/* +================== +CopyWinding +================== +*/ +winding_t *CopyWinding (winding_t *w) +{ + int size; + winding_t *c; + + c = AllocWinding (w->numpoints); + c->numpoints = w->numpoints; + size = w->numpoints*sizeof(w->p[0]); + memcpy (c->p, w->p, size); + return c; +} + +/* +================== +ReverseWinding +================== +*/ +winding_t *ReverseWinding (winding_t *w) +{ + int i; + winding_t *c; + + c = AllocWinding (w->numpoints); + for (i=0 ; inumpoints ; i++) + { + VectorCopy (w->p[w->numpoints-1-i], c->p[i]); + } + c->numpoints = w->numpoints; + return c; +} + + +// BUGBUG: Hunt this down - it's causing CSG errors +#pragma optimize("g", off) +/* +============= +ClipWindingEpsilon +============= +*/ + +void ClipWindingEpsilon (winding_t *in, const Vector &normal, vec_t dist, + vec_t epsilon, winding_t **front, winding_t **back) +{ + vec_t dists[MAX_POINTS_ON_WINDING+4]; + int sides[MAX_POINTS_ON_WINDING+4]; + int counts[3]; + vec_t dot; + int i, j; + Vector mid = vec3_origin; + winding_t *f, *b; + int maxpts; + + counts[0] = counts[1] = counts[2] = 0; + +// determine sides for each point + for (i=0 ; inumpoints ; i++) + { + dot = DotProduct (in->p[i], normal); + dot -= dist; + dists[i] = dot; + if (dot > epsilon) + sides[i] = SIDE_FRONT; + else if (dot < -epsilon) + sides[i] = SIDE_BACK; + else + { + sides[i] = SIDE_ON; + } + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + *front = *back = NULL; + + if (!counts[0]) + { + *back = CopyWinding (in); + return; + } + if (!counts[1]) + { + *front = CopyWinding (in); + return; + } + + maxpts = in->numpoints+4; // cant use counts[0]+2 because + // of fp grouping errors + + *front = f = AllocWinding (maxpts); + *back = b = AllocWinding (maxpts); + + for (i=0 ; inumpoints ; i++) + { + Vector& p1 = in->p[i]; + + if (sides[i] == SIDE_ON) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + VectorCopy (p1, b->p[b->numpoints]); + b->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + } + if (sides[i] == SIDE_BACK) + { + VectorCopy (p1, b->p[b->numpoints]); + b->numpoints++; + } + + if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + // generate a split point + Vector& p2 = in->p[(i+1)%in->numpoints]; + + dot = dists[i] / (dists[i]-dists[i+1]); + for (j=0 ; j<3 ; j++) + { // avoid round off error when possible + if (normal[j] == 1) + mid[j] = dist; + else if (normal[j] == -1) + mid[j] = -dist; + else + mid[j] = p1[j] + dot*(p2[j]-p1[j]); + } + + VectorCopy (mid, f->p[f->numpoints]); + f->numpoints++; + VectorCopy (mid, b->p[b->numpoints]); + b->numpoints++; + } + + if (f->numpoints > maxpts || b->numpoints > maxpts) + Error ("ClipWinding: points exceeded estimate"); + if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING) + Error ("ClipWinding: MAX_POINTS_ON_WINDING"); +} +#pragma optimize("", on) + + +// NOTE: This is identical to ClipWindingEpsilon, but it does a pre/post translation to improve precision +void ClipWindingEpsilon_Offset( winding_t *in, const Vector &normal, vec_t dist, vec_t epsilon, winding_t **front, winding_t **back, const Vector &offset ) +{ + TranslateWinding( in, offset ); + ClipWindingEpsilon( in, normal, dist+DotProduct(offset,normal), epsilon, front, back ); + TranslateWinding( in, -offset ); + if ( front && *front ) + { + TranslateWinding( *front, -offset ); + } + if ( back && *back ) + { + TranslateWinding( *back, -offset ); + } +} + +void ClassifyWindingEpsilon_Offset( winding_t *in, const Vector &normal, vec_t dist, vec_t epsilon, winding_t **front, winding_t **back, winding_t **on, const Vector &offset) +{ + TranslateWinding( in, offset ); + ClassifyWindingEpsilon( in, normal, dist+DotProduct(offset,normal), epsilon, front, back, on ); + TranslateWinding( in, -offset ); + if ( front && *front ) + { + TranslateWinding( *front, -offset ); + } + if ( back && *back ) + { + TranslateWinding( *back, -offset ); + } + if ( on && *on ) + { + TranslateWinding( *on, -offset ); + } +} + +/* +============= +ClassifyWindingEpsilon +============= +*/ +// This version returns the winding as "on" if all verts lie in the plane +void ClassifyWindingEpsilon( winding_t *in, const Vector &normal, vec_t dist, + vec_t epsilon, winding_t **front, winding_t **back, winding_t **on) +{ + vec_t dists[MAX_POINTS_ON_WINDING+4]; + int sides[MAX_POINTS_ON_WINDING+4]; + int counts[3]; + vec_t dot; + int i, j; + Vector mid = vec3_origin; + winding_t *f, *b; + int maxpts; + + counts[0] = counts[1] = counts[2] = 0; + +// determine sides for each point + for (i=0 ; inumpoints ; i++) + { + dot = DotProduct (in->p[i], normal); + dot -= dist; + dists[i] = dot; + if (dot > epsilon) + sides[i] = SIDE_FRONT; + else if (dot < -epsilon) + sides[i] = SIDE_BACK; + else + { + sides[i] = SIDE_ON; + } + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + *front = *back = *on = NULL; + + if ( !counts[0] && !counts[1] ) + { + *on = CopyWinding(in); + return; + } + + if (!counts[0]) + { + *back = CopyWinding(in); + return; + } + if (!counts[1]) + { + *front = CopyWinding(in); + return; + } + + maxpts = in->numpoints+4; // cant use counts[0]+2 because + // of fp grouping errors + + *front = f = AllocWinding (maxpts); + *back = b = AllocWinding (maxpts); + + for (i=0 ; inumpoints ; i++) + { + Vector& p1 = in->p[i]; + + if (sides[i] == SIDE_ON) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + VectorCopy (p1, b->p[b->numpoints]); + b->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + } + if (sides[i] == SIDE_BACK) + { + VectorCopy (p1, b->p[b->numpoints]); + b->numpoints++; + } + + if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + // generate a split point + Vector& p2 = in->p[(i+1)%in->numpoints]; + + dot = dists[i] / (dists[i]-dists[i+1]); + for (j=0 ; j<3 ; j++) + { // avoid round off error when possible + if (normal[j] == 1) + mid[j] = dist; + else if (normal[j] == -1) + mid[j] = -dist; + else + mid[j] = p1[j] + dot*(p2[j]-p1[j]); + } + + VectorCopy (mid, f->p[f->numpoints]); + f->numpoints++; + VectorCopy (mid, b->p[b->numpoints]); + b->numpoints++; + } + + if (f->numpoints > maxpts || b->numpoints > maxpts) + Error ("ClipWinding: points exceeded estimate"); + if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING) + Error ("ClipWinding: MAX_POINTS_ON_WINDING"); +} + +/* +============= +ChopWindingInPlace +============= +*/ +void ChopWindingInPlace (winding_t **inout, const Vector &normal, vec_t dist, vec_t epsilon) +{ + winding_t *in; + vec_t dists[MAX_POINTS_ON_WINDING+4]; + int sides[MAX_POINTS_ON_WINDING+4]; + int counts[3]; + vec_t dot; + int i, j; + Vector mid = vec3_origin; + winding_t *f; + int maxpts; + + in = *inout; + counts[0] = counts[1] = counts[2] = 0; +// determine sides for each point + for (i=0 ; inumpoints ; i++) + { + dot = DotProduct (in->p[i], normal); + dot -= dist; + dists[i] = dot; + if (dot > epsilon) + { + sides[i] = SIDE_FRONT; + } + else if (dot < -epsilon) + { + sides[i] = SIDE_BACK; + } + else + { + sides[i] = SIDE_ON; + } + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + if (!counts[0]) + { + FreeWinding (in); + *inout = NULL; + return; + } + if (!counts[1]) + return; // inout stays the same + + maxpts = in->numpoints+4; // cant use counts[0]+2 because + // of fp grouping errors + + f = AllocWinding (maxpts); + + for (i=0 ; inumpoints ; i++) + { + Vector& p1 = in->p[i]; + + if (sides[i] == SIDE_ON) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + } + + if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + // generate a split point + Vector& p2 = in->p[(i+1)%in->numpoints]; + + dot = dists[i] / (dists[i]-dists[i+1]); + for (j=0 ; j<3 ; j++) + { // avoid round off error when possible + if (normal[j] == 1) + mid[j] = dist; + else if (normal[j] == -1) + mid[j] = -dist; + else + mid[j] = p1[j] + dot*(p2[j]-p1[j]); + } + + VectorCopy (mid, f->p[f->numpoints]); + f->numpoints++; + } + + if (f->numpoints > maxpts) + Error ("ClipWinding: points exceeded estimate"); + if (f->numpoints > MAX_POINTS_ON_WINDING) + Error ("ClipWinding: MAX_POINTS_ON_WINDING"); + + FreeWinding (in); + *inout = f; +} + + +/* +================= +ChopWinding + +Returns the fragment of in that is on the front side +of the cliping plane. The original is freed. +================= +*/ +winding_t *ChopWinding (winding_t *in, const Vector &normal, vec_t dist) +{ + winding_t *f, *b; + + ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b); + FreeWinding (in); + if (b) + FreeWinding (b); + return f; +} + + +/* +================= +CheckWinding + +================= +*/ +void CheckWinding (winding_t *w) +{ + int i, j; + vec_t d, edgedist; + Vector dir, edgenormal, facenormal; + vec_t area; + vec_t facedist; + + if (w->numpoints < 3) + Error ("CheckWinding: %i points",w->numpoints); + + area = WindingArea(w); + if (area < 1) + Error ("CheckWinding: %f area", area); + + WindingPlane (w, facenormal, &facedist); + + for (i=0 ; inumpoints ; i++) + { + Vector& p1 = w->p[i]; + + for (j=0 ; j<3 ; j++) + { + if (p1[j] > MAX_COORD_INTEGER || p1[j] < MIN_COORD_INTEGER) + Error ("CheckFace: out of range: %f",p1[j]); + } + + j = i+1 == w->numpoints ? 0 : i+1; + + // check the point is on the face plane + d = DotProduct (p1, facenormal) - facedist; + if (d < -ON_EPSILON || d > ON_EPSILON) + Error ("CheckWinding: point off plane"); + + // check the edge isnt degenerate + Vector& p2 = w->p[j]; + VectorSubtract (p2, p1, dir); + + if (VectorLength (dir) < ON_EPSILON) + Error ("CheckWinding: degenerate edge"); + + CrossProduct (facenormal, dir, edgenormal); + VectorNormalize (edgenormal); + edgedist = DotProduct (p1, edgenormal); + edgedist += ON_EPSILON; + + // all other points must be on front side + for (j=0 ; jnumpoints ; j++) + { + if (j == i) + continue; + d = DotProduct (w->p[j], edgenormal); + if (d > edgedist) + Error ("CheckWinding: non-convex"); + } + } +} + + +/* +============ +WindingOnPlaneSide +============ +*/ +int WindingOnPlaneSide (winding_t *w, const Vector &normal, vec_t dist) +{ + qboolean front, back; + int i; + vec_t d; + + front = false; + back = false; + for (i=0 ; inumpoints ; i++) + { + d = DotProduct (w->p[i], normal) - dist; + if (d < -ON_EPSILON) + { + if (front) + return SIDE_CROSS; + back = true; + continue; + } + if (d > ON_EPSILON) + { + if (back) + return SIDE_CROSS; + front = true; + continue; + } + } + + if (back) + return SIDE_BACK; + if (front) + return SIDE_FRONT; + return SIDE_ON; +} + + +//----------------------------------------------------------------------------- +// Purpose: 2d point inside of winding test (assumes the point resides in the +// winding plane) +//----------------------------------------------------------------------------- +bool PointInWinding( const Vector &pt, winding_t *pWinding ) +{ + if( !pWinding ) + return false; + +#if 0 + // + // NOTE: this will be a quicker way to calculate this, however I don't + // know the trick off hand (post dot product tests??) + // TODO: look in graphics gems!!!! (cab) + // + + Vector edge1, edge2; + for( int ndxPt = 0; ndxPt < pWinding->numpoints; ndxPt++ ) + { + edge1 = pWinding->p[ndxPt] - pt; + edge2 = pWinding->p[(ndxPt+1)%pWinding->numpoints] - pt; + + VectorNormalize( edge1 ); + VectorNormalize( edge2 ); + + if( edge2.Dot( edge1 ) < 0.0f ) + return false; + } + + return true; + +#else + Vector edge, toPt, cross, testCross; + + // + // get the first normal to test + // + toPt = pt - pWinding->p[0]; + edge = pWinding->p[1] - pWinding->p[0]; + testCross = edge.Cross( toPt ); + VectorNormalize( testCross ); + + for( int ndxPt = 1; ndxPt < pWinding->numpoints; ndxPt++ ) + { + toPt = pt - pWinding->p[ndxPt]; + edge = pWinding->p[(ndxPt+1)%pWinding->numpoints] - pWinding->p[ndxPt]; + cross = edge.Cross( toPt ); + VectorNormalize( cross ); + + if( cross.Dot( testCross ) < 0.0f ) + return false; + } + + return true; +#endif +} + +void TranslateWinding( winding_t *pWinding, const Vector &offset ) +{ + for ( int i = 0; i < pWinding->numpoints; i++ ) + { + pWinding->p[i] += offset; + } +} diff --git a/utils/common/polylib.h b/utils/common/polylib.h new file mode 100644 index 00000000..3322214b --- /dev/null +++ b/utils/common/polylib.h @@ -0,0 +1,78 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef POLYLIB_H +#define POLYLIB_H +#pragma once + +#ifndef MATHLIB_H +#include "mathlib.h" +#endif + +struct winding_t +{ + int numpoints; + Vector *p; // variable sized + int maxpoints; + winding_t *next; +}; + +#define MAX_POINTS_ON_WINDING 64 + +// you can define on_epsilon in the makefile as tighter +// point on plane side epsilon +// todo: need a world-space epsilon, a lightmap-space epsilon, and a texture space epsilon +// or at least convert from a world-space epsilon to lightmap and texture space epsilons +#ifndef ON_EPSILON +#define ON_EPSILON 0.1 +#endif + + +winding_t *AllocWinding (int points); +vec_t WindingArea (winding_t *w); +void WindingCenter (winding_t *w, Vector ¢er); +vec_t WindingAreaAndBalancePoint( winding_t *w, Vector ¢er ); +void ClipWindingEpsilon (winding_t *in, const Vector &normal, vec_t dist, + vec_t epsilon, winding_t **front, winding_t **back); + +// translates everything by offset, then does the clip, then translates back (to keep precision) +void ClipWindingEpsilon_Offset( winding_t *in, const Vector &normal, vec_t dist, vec_t epsilon, winding_t **front, winding_t **back, const Vector &offset ); + +void ClassifyWindingEpsilon( winding_t *in, const Vector &normal, vec_t dist, + vec_t epsilon, winding_t **front, winding_t **back, winding_t **on); +void ClassifyWindingEpsilon_Offset( winding_t *in, const Vector &normal, vec_t dist, + vec_t epsilon, winding_t **front, winding_t **back, winding_t **on, const Vector &offset); + +winding_t *ChopWinding (winding_t *in, const Vector &normal, vec_t dist); +winding_t *CopyWinding (winding_t *w); +winding_t *ReverseWinding (winding_t *w); +winding_t *BaseWindingForPlane (const Vector &normal, vec_t dist); +void CheckWinding (winding_t *w); +void WindingPlane (winding_t *w, Vector &normal, vec_t *dist); +void RemoveColinearPoints (winding_t *w); +int WindingOnPlaneSide (winding_t *w, const Vector &normal, vec_t dist); +void FreeWinding (winding_t *w); +void WindingBounds (winding_t *w, Vector &mins, Vector &maxs); + +void ChopWindingInPlace (winding_t **w, const Vector &normal, vec_t dist, vec_t epsilon); +// frees the original if clipped + +bool PointInWinding( Vector const &pt, winding_t *pWinding ); + +// translates a winding by offset +void TranslateWinding( winding_t *pWinding, const Vector &offset ); + +void pw(winding_t *w); + + +#endif // POLYLIB_H diff --git a/utils/common/qfiles.h b/utils/common/qfiles.h new file mode 100644 index 00000000..dea264d0 --- /dev/null +++ b/utils/common/qfiles.h @@ -0,0 +1,42 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef QFILES_H +#define QFILES_H +#pragma once + + +// +// qfiles.h: quake file formats +// This file must be identical in the quake and utils directories +// + +#include "basetypes.h" +#include "commonmacros.h" +#include "worldsize.h" +#include "bspfile.h" + +#define MAX_OSPATH 260 +#define MAX_QPATH 64 + +/* +======================================================================== + +The .pak files are just a linear collapse of a directory tree + +======================================================================== +*/ + +#define IDPAKHEADER (('K'<<24)+('C'<<16)+('A'<<8)+'P') + +#endif // QFILES_H diff --git a/utils/common/scratchpad_helpers.cpp b/utils/common/scratchpad_helpers.cpp new file mode 100644 index 00000000..23c781cb --- /dev/null +++ b/utils/common/scratchpad_helpers.cpp @@ -0,0 +1,103 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "scratchpad_helpers.h" +#include "bspfile.h" +#include "bsplib.h" + + +void ScratchPad_DrawWinding( + IScratchPad3D *pPad, + int nPoints, + Vector *pPoints, + Vector vColor, + Vector vOffset ) +{ + for ( int i=0; i < nPoints; i++ ) + { + pPad->DrawLine( CSPVert( pPoints[i]+vOffset, vColor ), CSPVert( pPoints[(i+1)%nPoints]+vOffset, vColor ) ); + } +} + + +void ScratchPad_DrawFace( IScratchPad3D *pPad, dface_t *f, int iFaceNumber, const CSPColor &faceColor, const Vector &vOffset ) +{ + // Draw the face's outline, then put text for its face index on it too. + CUtlVector points; + for ( int iEdge = 0; iEdge < f->numedges; iEdge++ ) + { + int v; + int se = dsurfedges[f->firstedge + iEdge]; + if ( se < 0 ) + v = dedges[-se].v[1]; + else + v = dedges[se].v[0]; + + dvertex_t *dv = &dvertexes[v]; + points.AddToTail( dv->point ); + } + + // Draw the outline. + Vector vCenter( 0, 0, 0 ); + for ( int iEdge=0; iEdge < points.Count(); iEdge++ ) + { + pPad->DrawLine( CSPVert( points[iEdge]+vOffset, faceColor ), CSPVert( points[(iEdge+1)%points.Count()]+vOffset, faceColor ) ); + vCenter += points[iEdge]; + } + vCenter /= points.Count(); + vCenter += vOffset; + + // Draw the text. + if ( iFaceNumber != -1 ) + { + char str[64]; + Q_snprintf( str, sizeof( str ), "%d", iFaceNumber ); + + CTextParams params; + + params.m_bCentered = true; + params.m_bOutline = true; + params.m_flLetterWidth = 2; + params.m_vColor.Init( 1, 0, 0 ); + + VectorAngles( dplanes[f->planenum].normal, params.m_vAngles ); + params.m_bTwoSided = true; + + params.m_vPos = vCenter; + + pPad->DrawText( str, params ); + } +} + + +void ScratchPad_DrawWorld( IScratchPad3D *pPad, bool bDrawFaceNumbers, const CSPColor &faceColor ) +{ + bool bAutoFlush = pPad->GetAutoFlush(); + pPad->SetAutoFlush( false ); + + for ( int i=0; i < numleafs; i++ ) + { + dleaf_t *l = &dleafs[i]; + if ( l->contents & CONTENTS_DETAIL ) + continue; + + for ( int z=0; z < l->numleaffaces; z++ ) + { + int iFace = dleaffaces[l->firstleafface+z]; + dface_t *f = &dfaces[iFace]; + ScratchPad_DrawFace( pPad, f, bDrawFaceNumbers ? i : -1 ); + } + } + + pPad->SetAutoFlush( bAutoFlush ); +} + + +void ScratchPad_DrawWorld( bool bDrawFaceNumbers, const CSPColor &faceColor ) +{ + IScratchPad3D *pPad = ScratchPad3D_Create(); + ScratchPad_DrawWorld( pPad, bDrawFaceNumbers ); +} diff --git a/utils/common/scratchpad_helpers.h b/utils/common/scratchpad_helpers.h new file mode 100644 index 00000000..8f42637f --- /dev/null +++ b/utils/common/scratchpad_helpers.h @@ -0,0 +1,25 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef SCRATCHPAD_HELPERS_H +#define SCRATCHPAD_HELPERS_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "iscratchpad3d.h" +#include "bspfile.h" + + +void ScratchPad_DrawWinding( IScratchPad3D *pPad, int nPoints, Vector *pPoints, Vector vColor, Vector vOffset = Vector(0,0,0) ); + +void ScratchPad_DrawFace( IScratchPad3D *pPad, dface_t *f, int iFaceNumber = -1, const CSPColor &faceColor=CSPColor(1,1,1,1), const Vector &vOffset=Vector(0,0,0) ); +void ScratchPad_DrawWorld( IScratchPad3D *pPad, bool bDrawFaceNumbers, const CSPColor &faceColor=CSPColor(1,1,1,1) ); +void ScratchPad_DrawWorld( bool bDrawFaceNumbers, const CSPColor &faceColor=CSPColor(1,1,1,1) ); + + +#endif // SCRATCHPAD_HELPERS_H diff --git a/utils/common/scriplib.cpp b/utils/common/scriplib.cpp new file mode 100644 index 00000000..fc72c0db --- /dev/null +++ b/utils/common/scriplib.cpp @@ -0,0 +1,670 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +// scriplib.c + +#include "vstdlib/strtools.h" +#include "cmdlib.h" +#include "scriplib.h" +#ifdef STUDIOMDL +#include "studiomdl.h" +#endif + +/* +============================================================================= + + PARSING STUFF + +============================================================================= +*/ + +typedef struct +{ + char filename[1024]; + char *buffer,*script_p,*end_p; + int line; + + char macrobuffer[4096]; + char *macroparam[64]; + char *macrovalue[64]; + int nummacroparams; + +} script_t; + +#define MAX_INCLUDES 16 +script_t scriptstack[MAX_INCLUDES]; +script_t *script; +int scriptline; + +char token[MAXTOKEN]; +qboolean endofscript; +qboolean tokenready; // only true if UnGetToken was just called + +/* +============== +AddScriptToStack +============== +*/ +void AddScriptToStack (char *filename, ScriptPathMode_t pathMode = SCRIPT_USE_ABSOLUTE_PATH) +{ + int size; + + script++; + if (script == &scriptstack[MAX_INCLUDES]) + Error ("script file exceeded MAX_INCLUDES"); + + if ( pathMode == SCRIPT_USE_RELATIVE_PATH ) + Q_strncpy( script->filename, filename, sizeof( script->filename ) ); + else + Q_strncpy (script->filename, ExpandPath (filename), sizeof( script->filename ) ); + + size = LoadFile (script->filename, (void **)&script->buffer); + + // printf ("entering %s\n", script->filename); +#ifdef STUDIOMDL + extern bool g_bCreateMakefile; + if( g_bCreateMakefile ) + { + CreateMakefile_AddDependency( script->filename ); + } +#endif + + script->line = 1; + + script->script_p = script->buffer; + script->end_p = script->buffer + size; +} + + +/* +============== +LoadScriptFile +============== +*/ +void LoadScriptFile (char *filename, ScriptPathMode_t pathMode) +{ + script = scriptstack; + AddScriptToStack (filename, pathMode); + + endofscript = false; + tokenready = false; +} + + +/* +============== +============== +*/ + +script_t *macrolist[64]; +int nummacros; + +void DefineMacro( char *macroname ) +{ + script_t *pmacro = (script_t *)malloc( sizeof( script_t ) ); + + strcpy( pmacro->filename, macroname ); + pmacro->line = script->line; + pmacro->nummacroparams = 0; + + char *mp = pmacro->macrobuffer; + char *cp = script->script_p; + + while (TokenAvailable( )) + { + GetToken( false ); + + if (token[0] == '\\' && token[1] == '\\') + { + break; + } + cp = script->script_p; + + pmacro->macroparam[pmacro->nummacroparams++] = mp; + + strcpy( mp, token ); + mp += strlen( token ) + 1; + + if (mp >= pmacro->macrobuffer + sizeof( pmacro->macrobuffer )) + Error("Macro buffer overflow\n"); + } + // roll back script_p to previous valid location + script->script_p = cp; + + // find end of macro def + while (*cp && *cp != '\n') + { + //Msg("%d ", *cp ); + if (*cp == '\\' && *(cp+1) == '\\') + { + // skip till end of line + while (*cp && *cp != '\n') + { + *cp = ' '; // replace with spaces + cp++; + } + + if (*cp) + { + cp++; + } + } + else + { + cp++; + } + } + + int size = (cp - script->script_p); + + pmacro->buffer = (char *)malloc( size + 1); + memcpy( pmacro->buffer, script->script_p, size ); + pmacro->buffer[size] = '\0'; + pmacro->end_p = &pmacro->buffer[size]; + + macrolist[nummacros++] = pmacro; + + script->script_p = cp; +} + + +/* +============== +============== +*/ +bool AddMacroToStack( char *macroname ) +{ + // lookup macro + if (macroname[0] != '$') + return false; + + int i; + for (i = 0; i < nummacros; i++) + { + if (strcmpi( macrolist[i]->filename, ¯oname[1] ) == 0) + { + break; + } + } + if (i == nummacros) + return false; + + script_t *pmacro = macrolist[i]; + + // get tokens + script_t *pnext = script + 1; + + pnext++; + if (pnext == &scriptstack[MAX_INCLUDES]) + Error ("script file exceeded MAX_INCLUDES"); + + // get tokens + char *cp = pnext->macrobuffer; + + pnext->nummacroparams = pmacro->nummacroparams; + + for (i = 0; i < pnext->nummacroparams; i++) + { + GetToken(false); + + strcpy( cp, token ); + pnext->macroparam[i] = pmacro->macroparam[i]; + pnext->macrovalue[i] = cp; + + cp += strlen( token ) + 1; + + if (cp >= pnext->macrobuffer + sizeof( pnext->macrobuffer )) + Error("Macro buffer overflow\n"); + } + + script = pnext; + strcpy( script->filename, pmacro->filename ); + + int size = pmacro->end_p - pmacro->buffer; + script->buffer = (char *)malloc( size + 1 ); + memcpy( script->buffer, pmacro->buffer, size ); + pmacro->buffer[size] = '\0'; + script->script_p = script->buffer; + script->end_p = script->buffer + size; + script->line = pmacro->line; + + return true; +} + + + +bool ExpandMacroToken( char *&token_p ) +{ + if ( script->nummacroparams && *script->script_p == '$' ) + { + char *cp = script->script_p + 1; + + while ( *cp > 32 && *cp != '$' ) + { + cp++; + } + + // found a word with $'s on either end? + if (*cp != '$') + return false; + + // get token pointer + char *tp = script->script_p + 1; + int len = (cp - tp); + *(tp + len) = '\0'; + + // lookup macro parameter + int index = 0; + for (index = 0; index < script->nummacroparams; index++) + { + if (stricmp( script->macroparam[index], tp ) == 0) + break; + } + if (index >= script->nummacroparams) + { + Error("unknown macro token \"%s\" in %s\n", tp, script->filename ); + } + + // paste token into + len = strlen( script->macrovalue[index] ); + strcpy( token_p, script->macrovalue[index] ); + token_p += len; + + script->script_p = cp + 1; + + if (script->script_p >= script->end_p) + Error ("Macro expand overflow\n"); + + if (token_p >= &token[MAXTOKEN]) + Error ("Token too large on line %i\n",scriptline); + + return true; + } + return false; +} + + + +/* +============== +ParseFromMemory +============== +*/ +void ParseFromMemory (char *buffer, int size) +{ + script = scriptstack; + script++; + if (script == &scriptstack[MAX_INCLUDES]) + Error ("script file exceeded MAX_INCLUDES"); + strcpy (script->filename, "memory buffer" ); + + script->buffer = buffer; + script->line = 1; + script->script_p = script->buffer; + script->end_p = script->buffer + size; + + endofscript = false; + tokenready = false; +} + + +/* +============== +UnGetToken + +Signals that the current token was not used, and should be reported +for the next GetToken. Note that + +GetToken (true); +UnGetToken (); +GetToken (false); + +could cross a line boundary. +============== +*/ +void UnGetToken (void) +{ + tokenready = true; +} + + +qboolean EndOfScript (qboolean crossline) +{ + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + + if (!strcmp (script->filename, "memory buffer")) + { + endofscript = true; + return false; + } + + free (script->buffer); + script->buffer = NULL; + if (script == scriptstack+1) + { + endofscript = true; + return false; + } + script--; + scriptline = script->line; + // printf ("returning to %s\n", script->filename); + return GetToken (crossline); +} + +/* +============== +GetToken +============== +*/ +qboolean GetToken (qboolean crossline) +{ + char *token_p; + + if (tokenready) // is a token allready waiting? + { + tokenready = false; + return true; + } + + // printf("script_p %x (%x)\n", script->script_p, script->end_p ); fflush( stdout ); + + if (script->script_p >= script->end_p) + { + return EndOfScript (crossline); + } + + tokenready = false; + + // skip space, ctrl chars +skipspace: + while (*script->script_p <= 32) + { + if (script->script_p >= script->end_p) + { + return EndOfScript (crossline); + } + if (*(script->script_p++) == '\n') + { + if (!crossline) + { + Error ("Line %i is incomplete\n",scriptline); + } + scriptline = ++script->line; + } + } + + if (script->script_p >= script->end_p) + { + return EndOfScript (crossline); + } + + // strip single line comments + if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field + (*script->script_p == '/' && *((script->script_p)+1) == '/')) // also make // a comment field + { + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + while (*script->script_p++ != '\n') + { + if (script->script_p >= script->end_p) + { + return EndOfScript (crossline); + } + } + scriptline = ++script->line; + goto skipspace; + } + + // strip out matching /* */ comments + if (*script->script_p == '/' && *((script->script_p)+1) == '*') + { + script->script_p += 2; + while (*script->script_p != '*' || *((script->script_p)+1) != '/') + { + if (*script->script_p++ != '\n') + { + if (script->script_p >= script->end_p) + { + return EndOfScript (crossline); + } + + scriptline = ++script->line; + } + } + script->script_p += 2; + goto skipspace; + } + + // copy token to buffer + token_p = token; + + if (*script->script_p == '"') + { + // quoted token + script->script_p++; + while (*script->script_p != '"') + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[MAXTOKEN]) + Error ("Token too large on line %i\n",scriptline); + } + script->script_p++; + } + else // regular token + while ( *script->script_p > 32 && *script->script_p != ';') + { + if ( !ExpandMacroToken( token_p ) ) + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[MAXTOKEN]) + Error ("Token too large on line %i\n",scriptline); + } + } + + // add null to end of token + *token_p = 0; + + // check for other commands + if (!stricmp (token, "$include")) + { + GetToken (false); + AddScriptToStack (token); + return GetToken (crossline); + } + else if (!stricmp (token, "$definemacro")) + { + GetToken (false); + DefineMacro(token); + return GetToken (crossline); + } + else if (AddMacroToStack( token )) + { + return GetToken (crossline); + } + + return true; +} + + +/* +============== +GetExprToken - use C mathematical operator parsing rules to split tokens instead of whitespace +============== +*/ +qboolean GetExprToken (qboolean crossline) +{ + char *token_p; + + if (tokenready) // is a token allready waiting? + { + tokenready = false; + return true; + } + + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + + tokenready = false; + +// +// skip space +// +skipspace: + while (*script->script_p <= 32) + { + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + if (*script->script_p++ == '\n') + { + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + scriptline = ++script->line; + } + } + + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + + if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field + (*script->script_p == '/' && *((script->script_p)+1) == '/')) // also make // a comment field + { + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + while (*script->script_p++ != '\n') + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + goto skipspace; + } + +// +// copy token +// + token_p = token; + + if (*script->script_p == '"') + { + // quoted token + script->script_p++; + while (*script->script_p != '"') + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[MAXTOKEN]) + Error ("Token too large on line %i\n",scriptline); + } + script->script_p++; + } + else + { + if ( isalpha( *script->script_p ) || *script->script_p == '_' ) + { + // regular token + while ( isalnum( *script->script_p ) || *script->script_p == '_' ) + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[MAXTOKEN]) + Error ("Token too large on line %i\n",scriptline); + } + } + else if ( isdigit( *script->script_p ) || *script->script_p == '.' ) + { + // regular token + while ( isdigit( *script->script_p ) || *script->script_p == '.' ) + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[MAXTOKEN]) + Error ("Token too large on line %i\n",scriptline); + } + } + else + { + // single char + *token_p++ = *script->script_p++; + } + } + + *token_p = 0; + + if (!stricmp (token, "$include")) + { + GetToken (false); + AddScriptToStack (token); + return GetToken (crossline); + } + + return true; +} + + +/* +============== +TokenAvailable + +Returns true if there is another token on the line +============== +*/ +qboolean TokenAvailable (void) +{ + char *search_p; + + if (tokenready) // is a token allready waiting? + { + return true; + } + + search_p = script->script_p; + + if (search_p >= script->end_p) + return false; + + while ( *search_p <= 32) + { + if (*search_p == '\n') + return false; + search_p++; + if (search_p == script->end_p) + return false; + + } + + if (*search_p == ';' || *search_p == '#' || // semicolon and # is comment field + (*search_p == '/' && *((search_p)+1) == '/')) // also make // a comment field + return false; + + return true; +} + +qboolean GetTokenizerStatus( char **pFilename, int *pLine ) +{ + // is this the default state? + if (!script) + return false; + + if (script->script_p >= script->end_p) + return false; + + if (pFilename) + { + *pFilename = script->filename; + } + if (pLine) + { + *pLine = script->line; + } + return true; +} diff --git a/utils/common/scriplib.h b/utils/common/scriplib.h new file mode 100644 index 00000000..7c75f2b4 --- /dev/null +++ b/utils/common/scriplib.h @@ -0,0 +1,57 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//=============================================================================// + +#ifndef SCRIPLIB_H +#define SCRIPLIB_H + +#ifdef _WIN32 +#pragma once +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +enum ScriptPathMode_t +{ + SCRIPT_USE_ABSOLUTE_PATH, + SCRIPT_USE_RELATIVE_PATH +}; + + +// scriplib.h + +#define MAXTOKEN 1024 + +extern char token[MAXTOKEN]; +extern char *scriptbuffer,*script_p,*scriptend_p; +extern int grabbed; +extern int scriptline; +extern qboolean endofscript; + + +// If pathMode is SCRIPT_USE_ABSOLUTE_PATH, then it uses ExpandPath() on the filename before +// trying to open it. Otherwise, it passes the filename straight into the filesystem +// (so you can leave it as a relative path). +void LoadScriptFile (char *filename, ScriptPathMode_t pathMode=SCRIPT_USE_ABSOLUTE_PATH); +void ParseFromMemory (char *buffer, int size); + +qboolean GetToken (qboolean crossline); +qboolean GetExprToken (qboolean crossline); +void UnGetToken (void); +qboolean TokenAvailable (void); +qboolean GetTokenizerStatus( char **pFilename, int *pLine ); + +#ifdef __cplusplus +} +#endif + +#endif // SCRIPLIB_H diff --git a/utils/common/threads.cpp b/utils/common/threads.cpp new file mode 100644 index 00000000..bac05540 --- /dev/null +++ b/utils/common/threads.cpp @@ -0,0 +1,250 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//=============================================================================// + +#define USED + +#include +#include "cmdlib.h" +#define NO_THREAD_NAMES +#include "threads.h" +#include "pacifier.h" + +#define MAX_THREADS 16 + + +class CRunThreadsData +{ +public: + int m_iThread; + void *m_pUserData; + RunThreadsFn m_Fn; +}; + +CRunThreadsData g_RunThreadsData[MAX_THREADS]; + + +int dispatch; +int workcount; +qboolean pacifier; + +qboolean threaded; +bool g_bLowPriorityThreads = false; + +HANDLE g_ThreadHandles[MAX_THREADS]; + + + +/* +============= +GetThreadWork + +============= +*/ +int GetThreadWork (void) +{ + int r; + + ThreadLock (); + + if (dispatch == workcount) + { + ThreadUnlock (); + return -1; + } + + UpdatePacifier( (float)dispatch / workcount ); + + r = dispatch; + dispatch++; + ThreadUnlock (); + + return r; +} + + +ThreadWorkerFn workfunction; + +void ThreadWorkerFunction( int iThread, void *pUserData ) +{ + int work; + + while (1) + { + work = GetThreadWork (); + if (work == -1) + break; + + workfunction( iThread, work ); + } +} + +void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, ThreadWorkerFn func) +{ + if (numthreads == -1) + ThreadSetDefault (); + + workfunction = func; + RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction); +} + + +/* +=================================================================== + +WIN32 + +=================================================================== +*/ + +int numthreads = -1; +CRITICAL_SECTION crit; +static int enter; + + +class CCritInit +{ +public: + CCritInit() + { + InitializeCriticalSection (&crit); + } +} g_CritInit; + + + +void SetLowPriority() +{ + SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS ); +} + + +void ThreadSetDefault (void) +{ + SYSTEM_INFO info; + + if (numthreads == -1) // not set manually + { + GetSystemInfo (&info); + numthreads = info.dwNumberOfProcessors; + if (numthreads < 1 || numthreads > 32) + numthreads = 1; + } + + Msg ("%i threads\n", numthreads); +} + + +void ThreadLock (void) +{ + if (!threaded) + return; + EnterCriticalSection (&crit); + if (enter) + Error ("Recursive ThreadLock\n"); + enter = 1; +} + +void ThreadUnlock (void) +{ + if (!threaded) + return; + if (!enter) + Error ("ThreadUnlock without lock\n"); + enter = 0; + LeaveCriticalSection (&crit); +} + + +// This runs in the thread and dispatches a RunThreadsFn call. +DWORD WINAPI InternalRunThreadsFn( LPVOID pParameter ) +{ + CRunThreadsData *pData = (CRunThreadsData*)pParameter; + pData->m_Fn( pData->m_iThread, pData->m_pUserData ); + return 0; +} + + +void RunThreads_Start( RunThreadsFn fn, void *pUserData ) +{ + Assert( numthreads > 0 ); + threaded = true; + + if ( numthreads > MAX_TOOL_THREADS ) + numthreads = MAX_TOOL_THREADS; + + for ( int i=0; i < numthreads ;i++ ) + { + g_RunThreadsData[i].m_iThread = i; + g_RunThreadsData[i].m_pUserData = pUserData; + g_RunThreadsData[i].m_Fn = fn; + + DWORD dwDummy; + g_ThreadHandles[i] = CreateThread( + NULL, // LPSECURITY_ATTRIBUTES lpsa, + 0, // DWORD cbStack, + InternalRunThreadsFn, // LPTHREAD_START_ROUTINE lpStartAddr, + &g_RunThreadsData[i], // LPVOID lpvThreadParm, + 0, // DWORD fdwCreate, + &dwDummy ); + + if( g_bLowPriorityThreads ) + SetThreadPriority( g_ThreadHandles[i], THREAD_PRIORITY_LOWEST ); + } +} + + +void RunThreads_End() +{ + WaitForMultipleObjects( numthreads, g_ThreadHandles, TRUE, INFINITE ); + for ( int i=0; i < numthreads; i++ ) + CloseHandle( g_ThreadHandles[i] ); + + threaded = false; +} + + +/* +============= +RunThreadsOn +============= +*/ +void RunThreadsOn( int workcnt, qboolean showpacifier, RunThreadsFn fn, void *pUserData ) +{ + int start, end; + + start = Plat_FloatTime(); + dispatch = 0; + workcount = workcnt; + StartPacifier(""); + pacifier = showpacifier; + +#ifdef _PROFILE + threaded = false; + (*func)( 0 ); + return; +#endif + + + RunThreads_Start( fn, pUserData ); + RunThreads_End(); + + + end = Plat_FloatTime(); + if (pacifier) + { + EndPacifier(false); + printf (" (%i)\n", end-start); + } +} + + diff --git a/utils/common/threads.h b/utils/common/threads.h new file mode 100644 index 00000000..ac95c895 --- /dev/null +++ b/utils/common/threads.h @@ -0,0 +1,56 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef THREADS_H +#define THREADS_H +#pragma once + + +// Arrays that are indexed by thread should always be MAX_TOOL_THREADS+1 +// large so THREADINDEX_MAIN can be used from the main thread. +#define MAX_TOOL_THREADS 4 +#define THREADINDEX_MAIN 4 + + +extern int numthreads; + +// If set to true, then all the threads that are created are low priority. +extern bool g_bLowPriorityThreads; + +typedef void (*ThreadWorkerFn)( int iThread, int iWorkItem ); +typedef void (*RunThreadsFn)( int iThread, void *pUserData ); + +// Put the process into an idle priority class so it doesn't hog the UI. +void SetLowPriority(); + +void ThreadSetDefault (void); +int GetThreadWork (void); + +void RunThreadsOnIndividual ( int workcnt, qboolean showpacifier, ThreadWorkerFn fn ); + +void RunThreadsOn ( int workcnt, qboolean showpacifier, RunThreadsFn fn, void *pUserData=NULL ); + +// This version doesn't track work items - it just runs your function and waits for it to finish. +void RunThreads_Start( RunThreadsFn fn, void *pUserData ); +void RunThreads_End(); + +void ThreadLock (void); +void ThreadUnlock (void); + + +#ifndef NO_THREAD_NAMES +#define RunThreadsOn(n,p,f) { if (p) printf("%-20s ", #f ":"); RunThreadsOn(n,p,f); } +#define RunThreadsOnIndividual(n,p,f) { if (p) printf("%-20s ", #f ":"); RunThreadsOnIndividual(n,p,f); } +#endif + +#endif // THREADS_H diff --git a/utils/common/tools_minidump.cpp b/utils/common/tools_minidump.cpp new file mode 100644 index 00000000..3b233987 --- /dev/null +++ b/utils/common/tools_minidump.cpp @@ -0,0 +1,61 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include +#include "tier0/minidump.h" +#include "tools_minidump.h" + + +static bool g_bToolsWriteFullMinidumps = false; +static ToolsExceptionHandler g_pCustomExceptionHandler = false; + + +// --------------------------------------------------------------------------------- // +// Internal helpers. +// --------------------------------------------------------------------------------- // + +static LONG __stdcall ToolsExceptionFilter( struct _EXCEPTION_POINTERS *ExceptionInfo ) +{ + // Non VMPI workers write a minidump and show a crash dialog like normal. + int iType = MiniDumpNormal; + if ( g_bToolsWriteFullMinidumps ) + iType = MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory; + + WriteMiniDumpUsingExceptionInfo( ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo, (MINIDUMP_TYPE)iType ); + return EXCEPTION_CONTINUE_SEARCH; +} + + +static LONG __stdcall ToolsExceptionFilter_Custom( struct _EXCEPTION_POINTERS *ExceptionInfo ) +{ + // Run their custom handler. + g_pCustomExceptionHandler( ExceptionInfo->ExceptionRecord->ExceptionCode ); + return EXCEPTION_EXECUTE_HANDLER; // (never gets here anyway) +} + + +// --------------------------------------------------------------------------------- // +// Interface functions. +// --------------------------------------------------------------------------------- // + +void EnableFullMinidumps( bool bFull ) +{ + g_bToolsWriteFullMinidumps = bFull; +} + + +void SetupDefaultToolsMinidumpHandler() +{ + SetUnhandledExceptionFilter( ToolsExceptionFilter ); +} + + +void SetupToolsMinidumpHandler( ToolsExceptionHandler fn ) +{ + g_pCustomExceptionHandler = fn; + SetUnhandledExceptionFilter( ToolsExceptionFilter_Custom ); +} diff --git a/utils/common/tools_minidump.h b/utils/common/tools_minidump.h new file mode 100644 index 00000000..a69a7cba --- /dev/null +++ b/utils/common/tools_minidump.h @@ -0,0 +1,30 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef TOOLS_MINIDUMP_H +#define TOOLS_MINIDUMP_H +#ifdef _WIN32 +#pragma once +#endif + + + +// Defaults to false. If true, it'll write larger minidump files with the contents +// of global variables and following pointers from where the crash occurred. +void EnableFullMinidumps( bool bFull ); + + +// This handler catches any crash, writes a minidump, and runs the default system +// crash handler (which usually shows a dialog). +void SetupDefaultToolsMinidumpHandler(); + + +// (Used by VMPI) - you specify your own crash handler. +typedef void (*ToolsExceptionHandler)( unsigned long exceptionCode ); +void SetupToolsMinidumpHandler( ToolsExceptionHandler fn ); + + +#endif // MINIDUMP_H diff --git a/utils/common/utilmatlib.cpp b/utils/common/utilmatlib.cpp new file mode 100644 index 00000000..73ce6f68 --- /dev/null +++ b/utils/common/utilmatlib.cpp @@ -0,0 +1,184 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//=============================================================================// + +// C callable material system interface for the utils. + +#include +#include "materialsystem/IMaterialSystem.h" +#include "materialsystem/IMaterial.h" +#include "materialsystem/IMaterialVar.h" +#include +#include "utilmatlib.h" +#include "tier0/dbg.h" +#include "FileSystem.h" +#include "materialsystem/MaterialSystem_Config.h" +#include "Mathlib.h" + +void LoadMaterialSystemInterface( CreateInterfaceFn fileSystemFactory ) +{ + if( g_pMaterialSystem ) + return; + + // materialsystem.dll should be in the path, it's in bin along with vbsp. + const char *pDllName = "materialsystem.dll"; + CSysModule *materialSystemDLLHInst; + materialSystemDLLHInst = g_pFullFileSystem->LoadModule( pDllName ); + if( !materialSystemDLLHInst ) + { + Error( "Can't load MaterialSystem.dll\n" ); + } + + CreateInterfaceFn clientFactory = Sys_GetFactory( materialSystemDLLHInst ); + if ( clientFactory ) + { + g_pMaterialSystem = (IMaterialSystem *)clientFactory( MATERIAL_SYSTEM_INTERFACE_VERSION, NULL ); + if ( !g_pMaterialSystem ) + { + Error( "Could not get the material system interface from materialsystem.dll (" __FILE__ ")" ); + } + } + else + { + Error( "Could not find factory interface in library MaterialSystem.dll" ); + } + + if (!g_pMaterialSystem->Init( "shaderapiempty.dll", 0, fileSystemFactory )) + { + Error( "Could not start the empty shader (shaderapiempty.dll)!" ); + } +} + +void InitMaterialSystem( const char *materialBaseDirPath, CreateInterfaceFn fileSystemFactory ) +{ + LoadMaterialSystemInterface( fileSystemFactory ); + MaterialSystem_Config_t config; + g_pMaterialSystem->OverrideConfig( config, false ); +} + +void ShutdownMaterialSystem( ) +{ + if ( g_pMaterialSystem ) + { + g_pMaterialSystem->Shutdown(); + g_pMaterialSystem = NULL; + } +} + +MaterialSystemMaterial_t FindMaterial( const char *materialName, bool *pFound, bool bComplain ) +{ + IMaterial *pMat = g_pMaterialSystem->FindMaterial( materialName, TEXTURE_GROUP_OTHER, bComplain ); + MaterialSystemMaterial_t matHandle = pMat; + + if ( pFound ) + { + *pFound = true; + if ( IsErrorMaterial( pMat ) ) + *pFound = false; + } + + return matHandle; +} + +void GetMaterialDimensions( MaterialSystemMaterial_t materialHandle, int *width, int *height ) +{ + PreviewImageRetVal_t retVal; + ImageFormat dummyImageFormat; + IMaterial *material = ( IMaterial * )materialHandle; + bool translucent; + retVal = material->GetPreviewImageProperties( width, height, &dummyImageFormat, &translucent ); + if (retVal != MATERIAL_PREVIEW_IMAGE_OK ) + { +#if 0 + if (retVal == MATERIAL_PREVIEW_IMAGE_BAD ) + { + Error( "problem getting preview image for %s", + g_pMaterialSystem->GetMaterialName( materialInfo[matID].materialHandle ) ); + } +#else + *width = 128; + *height = 128; +#endif + } +} + +void GetMaterialReflectivity( MaterialSystemMaterial_t materialHandle, float *reflectivityVect ) +{ + IMaterial *material = ( IMaterial * )materialHandle; + const IMaterialVar *reflectivityVar; + + bool found; + reflectivityVar = material->FindVar( "$reflectivity", &found, false ); + if( !found ) + { + Vector tmp; + material->GetReflectivity( tmp ); + VectorCopy( tmp.Base(), reflectivityVect ); + } + else + { + reflectivityVar->GetVecValue( reflectivityVect, 3 ); + } +} + +int GetMaterialShaderPropertyBool( MaterialSystemMaterial_t materialHandle, int propID ) +{ + IMaterial *material = ( IMaterial * )materialHandle; + switch( propID ) + { + case UTILMATLIB_NEEDS_BUMPED_LIGHTMAPS: + return material->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_BUMPED_LIGHTMAPS ); + + case UTILMATLIB_NEEDS_LIGHTMAP: + return material->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_LIGHTMAP ); + + default: + Assert( 0 ); + return 0; + } +} + +int GetMaterialShaderPropertyInt( MaterialSystemMaterial_t materialHandle, int propID ) +{ + IMaterial *material = ( IMaterial * )materialHandle; + switch( propID ) + { + case UTILMATLIB_OPACITY: + if (material->IsTranslucent()) + return UTILMATLIB_TRANSLUCENT; + if (material->IsAlphaTested()) + return UTILMATLIB_ALPHATEST; + return UTILMATLIB_OPAQUE; + + default: + Assert( 0 ); + return 0; + } +} + +const char *GetMaterialVar( MaterialSystemMaterial_t materialHandle, const char *propertyName ) +{ + IMaterial *material = ( IMaterial * )materialHandle; + IMaterialVar *var; + bool found; + var = material->FindVar( propertyName, &found, false ); + if( found ) + { + return var->GetStringValue(); + } + else + { + return NULL; + } +} + +const char *GetMaterialShaderName( MaterialSystemMaterial_t materialHandle ) +{ + IMaterial *material = ( IMaterial * )materialHandle; + return material->GetShaderName(); +} diff --git a/utils/common/utilmatlib.h b/utils/common/utilmatlib.h new file mode 100644 index 00000000..113366bb --- /dev/null +++ b/utils/common/utilmatlib.h @@ -0,0 +1,41 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//=============================================================================// + +#ifndef UTILMATLIB_H +#define UTILMATLIB_H + +#ifdef _WIN32 +#pragma once +#endif + +#define MATERIAL_NOT_FOUND NULL + +class IMaterialSystem; +extern IMaterialSystem *g_pMaterialSystem; + +typedef void *MaterialSystemMaterial_t; + +#define UTILMATLIB_NEEDS_BUMPED_LIGHTMAPS 0 +#define UTILMATLIB_NEEDS_LIGHTMAP 1 +#define UTILMATLIB_OPACITY 2 + +enum { UTILMATLIB_ALPHATEST = 0, UTILMATLIB_OPAQUE, UTILMATLIB_TRANSLUCENT }; + +void InitMaterialSystem( const char *materialBaseDirPath, CreateInterfaceFn fileSystemFactory ); +void ShutdownMaterialSystem( ); +MaterialSystemMaterial_t FindMaterial( const char *materialName, bool *pFound, bool bComplain = true ); +void GetMaterialDimensions( MaterialSystemMaterial_t materialHandle, int *width, int *height ); +int GetMaterialShaderPropertyBool( MaterialSystemMaterial_t materialHandle, int propID ); +int GetMaterialShaderPropertyInt( MaterialSystemMaterial_t materialHandle, int propID ); +const char *GetMaterialVar( MaterialSystemMaterial_t materialHandle, const char *propertyName ); +void GetMaterialReflectivity( MaterialSystemMaterial_t materialHandle, float *reflectivityVect ); +const char *GetMaterialShaderName( MaterialSystemMaterial_t materialHandle ); + + +#endif // UTILMATLIB_H diff --git a/utils/common/vmpi_tools_shared.cpp b/utils/common/vmpi_tools_shared.cpp new file mode 100644 index 00000000..b60644e8 --- /dev/null +++ b/utils/common/vmpi_tools_shared.cpp @@ -0,0 +1,234 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include +#include "vmpi.h" +#include "cmdlib.h" +#include "vmpi_tools_shared.h" +#include "vstdlib/strtools.h" +#include "mpi_stats.h" +#include "iphelpers.h" + + +// ----------------------------------------------------------------------------- // +// Globals. +// ----------------------------------------------------------------------------- // + +static bool g_bReceivedDirectoryInfo = false; // Have we gotten the qdir info yet? + +static bool g_bReceivedDBInfo = false; +static CDBInfo g_DBInfo; +static unsigned long g_JobPrimaryID; + +static int g_nDisconnects = 0; // Tracks how many remote processes have disconnected ungracefully. + + +// ----------------------------------------------------------------------------- // +// Shared dispatch code. +// ----------------------------------------------------------------------------- // + +bool SharedDispatch( MessageBuffer *pBuf, int iSource, int iPacketID ) +{ + char *pInPos = &pBuf->data[2]; + + switch ( pBuf->data[1] ) + { + case VMPI_SUBPACKETID_DIRECTORIES: + { + Q_strncpy( gamedir, pInPos, sizeof( gamedir ) ); + pInPos += strlen( pInPos ) + 1; + + Q_strncpy( qdir, pInPos, sizeof( qdir ) ); + + g_bReceivedDirectoryInfo = true; + } + return true; + + case VMPI_SUBPACKETID_DBINFO: + { + g_DBInfo = *((CDBInfo*)pInPos); + pInPos += sizeof( CDBInfo ); + g_JobPrimaryID = *((unsigned long*)pInPos); + + g_bReceivedDBInfo = true; + } + return true; + + case VMPI_SUBPACKETID_CRASH: + { + Warning( "\nWorker '%s' dead: %s\n", VMPI_GetMachineName( iSource ), pInPos ); + } + return true; + } + + return false; +} + +CDispatchReg g_SharedDispatchReg( VMPI_SHARED_PACKET_ID, SharedDispatch ); + + + +// ----------------------------------------------------------------------------- // +// Module interfaces. +// ----------------------------------------------------------------------------- // + +void SendQDirInfo() +{ + char cPacketID[2] = { VMPI_SHARED_PACKET_ID, VMPI_SUBPACKETID_DIRECTORIES }; + + MessageBuffer mb; + mb.write( cPacketID, 2 ); + mb.write( gamedir, strlen( gamedir ) + 1 ); + mb.write( qdir, strlen( qdir ) + 1 ); + + VMPI_SendData( mb.data, mb.getLen(), VMPI_PERSISTENT ); +} + + +void RecvQDirInfo() +{ + while ( !g_bReceivedDirectoryInfo ) + VMPI_DispatchNextMessage(); +} + + +void SendDBInfo( const CDBInfo *pInfo, unsigned long jobPrimaryID ) +{ + char cPacketInfo[2] = { VMPI_SHARED_PACKET_ID, VMPI_SUBPACKETID_DBINFO }; + const void *pChunks[] = { cPacketInfo, pInfo, &jobPrimaryID }; + int chunkLengths[] = { 2, sizeof( CDBInfo ), sizeof( jobPrimaryID ) }; + + VMPI_SendChunks( pChunks, chunkLengths, ARRAYSIZE( pChunks ), VMPI_PERSISTENT ); +} + + +void RecvDBInfo( CDBInfo *pInfo, unsigned long *pJobPrimaryID ) +{ + while ( !g_bReceivedDBInfo ) + VMPI_DispatchNextMessage(); + + *pInfo = g_DBInfo; + *pJobPrimaryID = g_JobPrimaryID; +} + + +void VMPI_HandleCrash( const char *pMessage, bool bAssert ) +{ + static LONG crashHandlerCount = 0; + if ( InterlockedIncrement( &crashHandlerCount ) == 1 ) + { + Msg( "\nFAILURE: '%s' (assert: %d)\n", pMessage, bAssert ); + + // Send a message to the master. + char crashMsg[2] = { VMPI_SHARED_PACKET_ID, VMPI_SUBPACKETID_CRASH }; + + VMPI_Send2Chunks( + crashMsg, + sizeof( crashMsg ), + pMessage, + strlen( pMessage ) + 1, + VMPI_MASTER_ID ); + + // Let the messages go out. + Sleep( 500 ); + } + + InterlockedDecrement( &crashHandlerCount ); +} + + +// This is called if we crash inside our crash handler. It just terminates the process immediately. +LONG __stdcall VMPI_SecondExceptionFilter( struct _EXCEPTION_POINTERS *ExceptionInfo ) +{ + TerminateProcess( GetCurrentProcess(), 2 ); + return EXCEPTION_EXECUTE_HANDLER; // (never gets here anyway) +} + + +void VMPI_ExceptionFilter( unsigned long code ) +{ + // This is called if we crash inside our crash handler. It just terminates the process immediately. + SetUnhandledExceptionFilter( VMPI_SecondExceptionFilter ); + + //DWORD code = ExceptionInfo->ExceptionRecord->ExceptionCode; + + #define ERR_RECORD( name ) { name, #name } + struct + { + int code; + char *pReason; + } errors[] = + { + ERR_RECORD( EXCEPTION_ACCESS_VIOLATION ), + ERR_RECORD( EXCEPTION_ARRAY_BOUNDS_EXCEEDED ), + ERR_RECORD( EXCEPTION_BREAKPOINT ), + ERR_RECORD( EXCEPTION_DATATYPE_MISALIGNMENT ), + ERR_RECORD( EXCEPTION_FLT_DENORMAL_OPERAND ), + ERR_RECORD( EXCEPTION_FLT_DIVIDE_BY_ZERO ), + ERR_RECORD( EXCEPTION_FLT_INEXACT_RESULT ), + ERR_RECORD( EXCEPTION_FLT_INVALID_OPERATION ), + ERR_RECORD( EXCEPTION_FLT_OVERFLOW ), + ERR_RECORD( EXCEPTION_FLT_STACK_CHECK ), + ERR_RECORD( EXCEPTION_FLT_UNDERFLOW ), + ERR_RECORD( EXCEPTION_ILLEGAL_INSTRUCTION ), + ERR_RECORD( EXCEPTION_IN_PAGE_ERROR ), + ERR_RECORD( EXCEPTION_INT_DIVIDE_BY_ZERO ), + ERR_RECORD( EXCEPTION_INT_OVERFLOW ), + ERR_RECORD( EXCEPTION_INVALID_DISPOSITION ), + ERR_RECORD( EXCEPTION_NONCONTINUABLE_EXCEPTION ), + ERR_RECORD( EXCEPTION_PRIV_INSTRUCTION ), + ERR_RECORD( EXCEPTION_SINGLE_STEP ), + ERR_RECORD( EXCEPTION_STACK_OVERFLOW ), + ERR_RECORD( EXCEPTION_ACCESS_VIOLATION ), + }; + + int nErrors = sizeof( errors ) / sizeof( errors[0] ); + int i = 0; + for ( i = 0; i < nErrors; i++ ) + { + if ( errors[i].code == code ) + VMPI_HandleCrash( errors[i].pReason, true ); + } + + if ( i == nErrors ) + { + VMPI_HandleCrash( "Unknown reason", true ); + } + + TerminateProcess( GetCurrentProcess(), 1 ); +} + + +void HandleMPIDisconnect( int procID, const char *pReason ) +{ + int nLiveWorkers = VMPI_GetCurrentNumberOfConnections() - g_nDisconnects - 1; + + bool bOldSuppress = g_bSuppressPrintfOutput; + g_bSuppressPrintfOutput = true; + + Warning( "\n\n--- WARNING: lost connection to '%s' (%s).\n", VMPI_GetMachineName( procID ), pReason ); + + if ( g_bMPIMaster ) + { + Warning( "%d workers remain.\n\n", nLiveWorkers ); + + ++g_nDisconnects; + /* + if ( VMPI_GetCurrentNumberOfConnections() - g_nDisconnects <= 1 ) + { + Error( "All machines disconnected!" ); + } + */ + } + else + { + Error( "Worker quitting." ); + } + + g_bSuppressPrintfOutput = bOldSuppress; +} + + diff --git a/utils/common/vmpi_tools_shared.h b/utils/common/vmpi_tools_shared.h new file mode 100644 index 00000000..077ec8e2 --- /dev/null +++ b/utils/common/vmpi_tools_shared.h @@ -0,0 +1,46 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef VMPI_TOOLS_SHARED_H +#define VMPI_TOOLS_SHARED_H +#ifdef _WIN32 +#pragma once +#endif + + +// Packet IDs. +#define VMPI_SHARED_PACKET_ID 10 + + #define VMPI_SUBPACKETID_DIRECTORIES 0 // qdir directories. + #define VMPI_SUBPACKETID_DBINFO 1 // MySQL database info. + #define VMPI_SUBPACKETID_CRASH 3 // A worker saying it crashed. + #define VMPI_SUBPACKETID_MULTICAST_ADDR 4 // Filesystem multicast address. + + +class CDBInfo; +class CIPAddr; + + +// Send/receive the qdir info. +void SendQDirInfo(); +void RecvQDirInfo(); + +void SendDBInfo( const CDBInfo *pInfo, unsigned long jobPrimaryID ); +void RecvDBInfo( CDBInfo *pInfo, unsigned long *pJobPrimaryID ); + +void SendMulticastIP( const CIPAddr *pAddr ); +void RecvMulticastIP( CIPAddr *pAddr ); + +void VMPI_HandleCrash( const char *pMessage, bool bAssert ); + +// Call this from an exception handler (set by SetUnhandledExceptionHandler). +// Code is ExceptionInfo->ExceptionRecord->ExceptionCode. +void VMPI_ExceptionFilter( unsigned long code ); + +void HandleMPIDisconnect( int procID, const char *pReason ); + + +#endif // VMPI_TOOLS_SHARED_H diff --git a/utils/common/wadlib.c b/utils/common/wadlib.c new file mode 100644 index 00000000..4aff972d --- /dev/null +++ b/utils/common/wadlib.c @@ -0,0 +1,334 @@ +//========= Copyright © 1996-2005, Valve LLC, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// wad2lib.c + +#include +#include +#include +#include +#include +#include +#include +//#include +#include + +#ifdef NeXT +#include +#endif +#include "cmdlib.h" +#include "wadlib.h" +#include "commonmacros.h" + +/* +============================================================================ + + WAD READING + +============================================================================ +*/ + + +lumpinfo_t *lumpinfo; // location of each lump on disk +int numlumps; + +wadinfo_t header; +FILE *wadhandle; + + +/* +==================== +W_OpenWad +==================== +*/ +void W_OpenWad (char *filename) +{ + lumpinfo_t *lump_p; + unsigned i; + int length; + +// +// open the file and add to directory +// + wadhandle = SafeOpenRead (filename); + SafeRead (wadhandle, &header, sizeof(header)); + + if (!STRING_MATCHES_ID(header.identification,WAD_ID)) + Error ("Wad file %s doesn't have %s identifier\n",filename, WAD_IDNAME); + + header.numlumps = LittleLong(header.numlumps); + header.infotableofs = LittleLong(header.infotableofs); + + numlumps = header.numlumps; + + length = numlumps*sizeof(lumpinfo_t); + lumpinfo = malloc (length); + lump_p = lumpinfo; + + fseek (wadhandle, header.infotableofs, SEEK_SET); + SafeRead (wadhandle, lumpinfo, length); + +// +// Fill in lumpinfo +// + + for (i=0 ; ifilepos = LittleLong(lump_p->filepos); + lump_p->size = LittleLong(lump_p->size); + } +} + + + +void CleanupName (char *in, char *out) +{ + int i; + + for (i=0 ; iname ) ; i++ ) + { + if (!in[i]) + break; + + out[i] = toupper(in[i]); + } + + for ( ; iname ); i++ ) + out[i] = 0; +} + + +/* +==================== +W_CheckNumForName + +Returns -1 if name not found +==================== +*/ +int W_CheckNumForName (char *name) +{ + char cleanname[TEXTURE_NAME_LENGTH]; + int v1,v2, v3, v4; + int i; + lumpinfo_t *lump_p; + + CleanupName (name, cleanname); + +// make the name into four integers for easy compares + + v1 = *(int *)cleanname; + v2 = *(int *)&cleanname[4]; + v3 = *(int *)&cleanname[8]; + v4 = *(int *)&cleanname[12]; + +// find it + + lump_p = lumpinfo; + for (i=0 ; iname == v1 + && *(int *)&lump_p->name[4] == v2 + && *(int *)&lump_p->name[8] == v3 + && *(int *)&lump_p->name[12] == v4 + && !strcmp( lump_p->name, cleanname ) ) + return i; + } + + return -1; +} + + +/* +==================== +W_GetNumForName + +Calls W_CheckNumForName, but bombs out if not found +==================== +*/ +int W_GetNumForName (char *name) +{ + int i; + + i = W_CheckNumForName (name); + if (i != -1) + return i; + + Error ("W_GetNumForName: %s not found!",name); + return -1; +} + + +/* +==================== +W_LumpLength + +Returns the buffer size needed to load the given lump +==================== +*/ +int W_LumpLength (int lump) +{ + if (lump >= numlumps) + Error ("W_LumpLength: %i >= numlumps",lump); + return lumpinfo[lump].size; +} + + +/* +==================== +W_ReadLumpNum + +Loads the lump into the given buffer, which must be >= W_LumpLength() +==================== +*/ +void W_ReadLumpNum (int lump, void *dest) +{ + lumpinfo_t *l; + + if (lump >= numlumps) + Error ("W_ReadLump: %i >= numlumps",lump); + l = lumpinfo+lump; + + fseek (wadhandle, l->filepos, SEEK_SET); + SafeRead (wadhandle, dest, l->size); +} + + + +/* +==================== +W_LoadLumpNum +==================== +*/ +void *W_LoadLumpNum (int lump) +{ + void *buf; + + if ((unsigned)lump >= numlumps) + Error ("W_CacheLumpNum: %i >= numlumps",lump); + + buf = malloc (W_LumpLength (lump)); + W_ReadLumpNum (lump, buf); + + return buf; +} + + +/* +==================== +W_LoadLumpName +==================== +*/ +void *W_LoadLumpName (char *name) +{ + return W_LoadLumpNum (W_GetNumForName(name)); +} + + +/* +=============================================================================== + + WAD CREATION + +=============================================================================== +*/ + +FILE *outwad; + +lumpinfo_t outinfo[4096]; +int outlumps; + +short (*wadshort) (short l); +int (*wadlong) (int l); + +/* +=============== +NewWad +=============== +*/ + +void NewWad (char *pathname, qboolean bigendien) +{ + outwad = SafeOpenWrite (pathname); + fseek (outwad, sizeof(wadinfo_t), SEEK_SET); + memset (outinfo, 0, sizeof(outinfo)); + + if (bigendien) + { + wadshort = BigShort; + wadlong = BigLong; + } + else + { + wadshort = LittleShort; + wadlong = LittleLong; + } + + outlumps = 0; +} + + +/* +=============== +AddLump +=============== +*/ + +void AddLump (char *name, void *buffer, int length, int type, int compress) +{ + lumpinfo_t *info; + int ofs; + + info = &outinfo[outlumps]; + outlumps++; + + memset (info,0,sizeof(info)); + + strcpy (info->name, name); + Q_strupr (info->name); + + ofs = ftell(outwad); + info->filepos = wadlong(ofs); + info->size = info->disksize = wadlong(length); + info->type = type; + info->compression = compress; + +// FIXME: do compression + + SafeWrite (outwad, buffer, length); +} + + +/* +=============== +WriteWad +=============== +*/ + +void WriteWad (int wad3) +{ + wadinfo_t header; + int ofs; + +// write the lumpingo + ofs = ftell(outwad); + + SafeWrite (outwad, outinfo, outlumps*sizeof(lumpinfo_t) ); + +// write the header + +// a program will be able to tell the ednieness of a wad by the id + ID_TO_STRING( WAD_ID, header.identification ); + + header.numlumps = wadlong(outlumps); + header.infotableofs = wadlong(ofs); + + fseek (outwad, 0, SEEK_SET); + SafeWrite (outwad, &header, sizeof(header)); + fclose (outwad); +} + + diff --git a/utils/common/wadlib.h b/utils/common/wadlib.h new file mode 100644 index 00000000..eb21d468 --- /dev/null +++ b/utils/common/wadlib.h @@ -0,0 +1,46 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +// wadlib.h + +// +// wad reading +// + +#define CMP_NONE 0 +#define CMP_LZSS 1 + +#define TYP_NONE 0 +#define TYP_LABEL 1 +#define TYP_LUMPY 64 // 64 + grab command number + +#ifndef WADTYPES_H +#include "wadtypes.h" +#endif + +extern lumpinfo_t *lumpinfo; // location of each lump on disk +extern int numlumps; +extern wadinfo_t header; + +void W_OpenWad (char *filename); +int W_CheckNumForName (char *name); +int W_GetNumForName (char *name); +int W_LumpLength (int lump); +void W_ReadLumpNum (int lump, void *dest); +void *W_LoadLumpNum (int lump); +void *W_LoadLumpName (char *name); + +void CleanupName (char *in, char *out); + +// +// wad creation +// +void NewWad (char *pathname, qboolean bigendien); +void AddLump (char *name, void *buffer, int length, int type, int compress); +void WriteWad (int wad3); + diff --git a/utils/mmsource/.gitignore b/utils/mmsource/.gitignore index c2f678d9..2479b5f9 100644 --- a/utils/mmsource/.gitignore +++ b/utils/mmsource/.gitignore @@ -25,4 +25,3 @@ Release.*/ # AMBuild build directories build/ obj-*/ -.gdb_history diff --git a/utils/mmsource/AMBuildScript b/utils/mmsource/AMBuildScript index 83653489..8e6cea24 100644 --- a/utils/mmsource/AMBuildScript +++ b/utils/mmsource/AMBuildScript @@ -8,38 +8,16 @@ class SDK(object): self.ext = ext self.code = aDef self.define = name + self.platform = platform self.name = dir self.path = None # Actual path - self.platformSpec = platform - - # By default, nothing supports x64. - if type(platform) is list: - self.platformSpec = {p: ['x86'] for p in platform} - else: - self.platformSpec = platform - - def shouldBuild(self, target, archs): - if target.platform not in self.platformSpec: - return False - if not len([i for i in self.platformSpec[target.platform] if i in archs]): - return False - return True WinOnly = ['windows'] WinLinux = ['windows', 'linux'] WinLinuxMac = ['windows', 'linux', 'mac'] -CSGO = { - 'windows': ['x86'], - 'linux': ['x86', 'x64'], - 'mac': ['x64'] -} -Source2 = { - 'windows': ['x86', 'x64'], - 'linux': ['x64'], -} PossibleSDKs = { - 'episode1': SDK('HL2SDK', '2.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'), + 'episode1': SDK('HL2SDK', '1.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'), 'ep2': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'orangebox'), 'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'), 'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', WinLinuxMac, 'hl2dm'), @@ -53,8 +31,8 @@ PossibleSDKs = { 'swarm': SDK('HL2SDK-SWARM', '2.swarm', '16', 'ALIENSWARM', WinOnly, 'swarm'), 'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'), 'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'), - 'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', CSGO, 'csgo'), - 'dota': SDK('HL2SDKDOTA', '2.dota', '22', 'DOTA', Source2, 'dota'), + 'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', WinLinuxMac, 'csgo'), + 'dota': SDK('HL2SDKDOTA', '2.dota', '22', 'DOTA', [], 'dota'), 'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '17', 'PORTAL2', [], 'portal2'), 'blade': SDK('HL2SDKBLADE', '2.blade', '18', 'BLADE', WinLinux, 'blade'), 'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '19', 'INSURGENCY', WinLinuxMac, 'insurgency'), @@ -78,28 +56,6 @@ def ResolveEnvPath(env, folder): oldhead = head head, tail = os.path.split(head) return None - -def SetArchFlags(compiler, arch, platform): - if compiler.behavior == 'gcc': - if arch == 'x86': - compiler.cflags += ['-m32'] - compiler.linkflags += ['-m32'] - if platform == 'mac': - compiler.linkflags += ['-arch', 'i386'] - elif arch == 'x64': - compiler.cflags += ['-m64', '-fPIC'] - compiler.linkflags += ['-m64'] - if platform == 'mac': - compiler.linkflags += ['-arch', 'x86_64'] - elif compiler.like('msvc'): - if arch == 'x86': - compiler.linkflags += ['/MACHINE:X86'] - elif arch == 'x64': - compiler.linkflags += ['/MACHINE:X64'] - -def AppendArchSuffix(binary, name, arch): - if arch == 'x64': - binary.localFolder = name + '.x64' class MMSConfig(object): def __init__(self): @@ -107,12 +63,6 @@ class MMSConfig(object): self.binaries = [] self.generated_headers = None self.versionlib = None - self.archs = builder.target.arch.replace('x86_64', 'x64').split(',') - - def use_auto_versioning(self): - if builder.backend != 'amb2': - return False - return not getattr(builder.options, 'disable_auto_versioning', False) def detectProductVersion(self): builder.AddConfigureFile('product.version') @@ -132,12 +82,10 @@ class MMSConfig(object): sdk_list = builder.options.sdks.split(',') use_all = sdk_list[0] == 'all' use_present = sdk_list[0] == 'present' - if sdk_list[0] == '': - sdk_list = [] for sdk_name in PossibleSDKs: sdk = PossibleSDKs[sdk_name] - if sdk.shouldBuild(builder.target, self.archs): + if builder.target_platform in sdk.platform: if builder.options.hl2sdk_root: sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder) else: @@ -150,23 +98,17 @@ class MMSConfig(object): sdk.path = sdk_path self.sdks[sdk_name] = sdk - if len(self.sdks) < 1 and len(sdk_list): - raise Exception('No SDKs were found that build on {0}-{1}, nothing to do.'.format( - builder.target.platform, builder.target.arch)) + if len(self.sdks) < 1: + raise Exception('At least one SDK must be available.') def configure(self): builder.AddConfigureFile('pushbuild.txt') - if not set(self.archs).issubset(['x86', 'x64']): - raise Exception('Unknown target architecture: {0}'.format(builder.target.arch)) - - cxx = builder.DetectCxx() - - if cxx.like('msvc') and len(self.archs) > 1: - raise Exception('Building multiple archs with MSVC is not currently supported') + cfg = builder.DetectCompilers() + cxx = cfg.cxx if cxx.behavior == 'gcc': - cxx.defines += [ + cfg.defines += [ 'stricmp=strcasecmp', '_stricmp=strcasecmp', '_snprintf=snprintf', @@ -174,7 +116,7 @@ class MMSConfig(object): 'HAVE_STDINT_H', 'GNUC', ] - cxx.cflags += [ + cfg.cflags += [ '-pipe', '-fno-strict-aliasing', '-Wall', @@ -183,52 +125,53 @@ class MMSConfig(object): '-Wno-unused', '-Wno-switch', '-msse', + '-m32', ] - cxx.cxxflags += [ '-std=c++11' ] - if (cxx.version >= 'gcc-4.0') or cxx.family == 'clang': - cxx.cflags += ['-fvisibility=hidden'] - cxx.cxxflags += ['-fvisibility-inlines-hidden'] - cxx.cxxflags += [ + cfg.cxxflags += [ '-std=c++11' ] + if (cxx.name == 'gcc' and cxx.majorVersion >= 4) or cxx.name == 'clang': + cfg.cflags += ['-fvisibility=hidden'] + cfg.cxxflags += ['-fvisibility-inlines-hidden'] + cfg.linkflags += ['-m32'] + cfg.cxxflags += [ '-fno-exceptions', '-fno-rtti', '-fno-threadsafe-statics', '-Wno-non-virtual-dtor', '-Wno-overloaded-virtual', ] - if (cxx.version >= 'gcc-4.7' or cxx.family == 'clang'): - cxx.cxxflags += ['-Wno-delete-non-virtual-dtor'] - if cxx.family == 'gcc': - cxx.cflags += ['-mfpmath=sse'] - if cxx.family == 'clang': - cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] - if cxx.version >= 'clang-3.9': - cxx.cxxflags += ['-Wno-expansion-to-defined'] - if cxx.version >= 'clang-3.6' or cxx.version >= 'apple-clang-7.0': - cxx.cxxflags += ['-Wno-inconsistent-missing-override'] - if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4': - cxx.cxxflags += ['-Wno-deprecated-register'] + if (cxx.name == 'gcc' and cfg.version >= 'gcc-4.7') or \ + (cxx.name == 'clang' and cxx.majorVersion >= 3): + cfg.cxxflags += ['-Wno-delete-non-virtual-dtor'] + if cxx.name == 'gcc': + cfg.cflags += ['-mfpmath=sse'] + if cxx.name == 'clang': + if cfg.version >= 'clang-3.6': + cfg.cxxflags += ['-Wno-inconsistent-missing-override'] + cfg.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] + if cfg.version >= 'apple-clang-5.1' or cfg.version >= 'clang-3.4': + cfg.cxxflags += ['-Wno-deprecated-register'] else: - cxx.cxxflags += ['-Wno-deprecated'] + cfg.cxxflags += ['-Wno-deprecated'] - elif cxx.like('msvc'): + elif cxx.name == 'msvc': if builder.options.debug == '1': - cxx.cflags += ['/MTd'] - cxx.linkflags += ['/NODEFAULTLIB:libcmt'] + cfg.cflags += ['/MTd'] + cfg.linkflags += ['/NODEFAULTLIB:libcmt'] else: - cxx.cflags += ['/MT'] - cxx.defines += [ + cfg.cflags += ['/MT'] + cfg.defines += [ '_CRT_SECURE_NO_DEPRECATE', '_CRT_SECURE_NO_WARNINGS', '_CRT_NONSTDC_NO_DEPRECATE', ] - cxx.cflags += [ + cfg.cflags += [ '/W3', '/Zi', ] - cxx.cxxflags += ['/TP'] - - cxx.linkflags += [ + cfg.cxxflags += ['/TP'] + cfg.linkflags += [ + '/MACHINE:X86', '/SUBSYSTEM:WINDOWS', 'kernel32.lib', 'user32.lib', @@ -242,68 +185,63 @@ class MMSConfig(object): 'uuid.lib', 'odbc32.lib', 'odbccp32.lib', - ] + ] # Optimization if builder.options.opt == '1': - cxx.defines += ['NDEBUG'] + cfg.defines += ['NDEBUG'] if cxx.behavior == 'gcc': - cxx.cflags += ['-O3'] + cfg.cflags += ['-O3'] elif cxx.behavior == 'msvc': - cxx.cflags += ['/Ox', '/Zo'] - cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] + cfg.cflags += ['/Ox', '/Zo'] + cfg.linkflags += ['/OPT:ICF', '/OPT:REF'] # Debugging if builder.options.debug == '1': - cxx.defines += ['DEBUG', '_DEBUG'] + cfg.defines += ['DEBUG', '_DEBUG'] if cxx.behavior == 'gcc': - cxx.cflags += ['-g3'] + cfg.cflags += ['-g3'] elif cxx.behavior == 'msvc': - cxx.cflags += ['/Od', '/RTC1'] + cfg.cflags += ['/Od', '/RTC1'] # This needs to be after our optimization flags which could otherwise disable it. - if cxx.family == 'msvc': + if cxx.name == 'msvc': # Don't omit the frame pointer. - cxx.cflags += ['/Oy-'] + cfg.cflags += ['/Oy-'] # Platform-specifics - if builder.target.platform == 'linux': - cxx.defines += ['_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64'] - if cxx.family == 'gcc': - cxx.linkflags += ['-static-libgcc'] - elif cxx.family == 'clang': - cxx.linkflags += ['-lgcc_eh'] - elif builder.target.platform == 'mac': - cxx.defines += ['OSX', '_OSX', 'POSIX'] - cxx.cflags += ['-mmacosx-version-min=10.5'] - cxx.linkflags += [ + if builder.target_platform == 'linux': + cfg.defines += ['_LINUX', 'POSIX'] + if cxx.name == 'gcc': + cfg.linkflags += ['-static-libgcc'] + elif cxx.name == 'clang': + cfg.linkflags += ['-lgcc_eh'] + elif builder.target_platform == 'mac': + cfg.defines += ['OSX', '_OSX', 'POSIX'] + cfg.cflags += ['-mmacosx-version-min=10.5'] + cfg.linkflags += [ '-mmacosx-version-min=10.5', - '-lc++', + '-arch', 'i386', + '-lstdc++', ] - elif builder.target.platform == 'windows': - cxx.defines += ['WIN32', '_WINDOWS'] + elif builder.target_platform == 'windows': + cfg.defines += ['WIN32', '_WINDOWS'] # Finish up. - cxx.defines += [ 'MMS_USE_VERSIONLIB' ] - cxx.includes += [ - os.path.join(builder.sourcePath, 'public'), - ] - if self.use_auto_versioning(): - cxx.defines += ['MMS_GENERATED_BUILD'] - cxx.includes += [ - os.path.join(builder.buildPath, 'includes'), - os.path.join(builder.sourcePath, 'versionlib'), - ] + cfg.defines += ['MMS_GENERATED_BUILD'] + cfg.includes += [os.path.join(builder.buildPath, 'includes')] + cfg.includes += [os.path.join(builder.sourcePath, 'versionlib')] + cfg.cxxincludes += [os.path.join(builder.sourcePath, 'public')] - def HL2Compiler(self, context, sdk, arch): - compiler = context.cxx.clone() + def HL2Compiler(self, context, sdk): + compiler = context.compiler.clone() compiler.cxxincludes += [ os.path.join(context.currentSourcePath), os.path.join(context.currentSourcePath, 'sourcehook'), os.path.join(context.sourcePath, 'loader'), ] - defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs] + defines = ['SE_' + self.sdks[i].define + '=' + self.sdks[i].code for i in self.sdks] compiler.defines += defines paths = [['public'], ['public', 'engine'], @@ -320,162 +258,101 @@ class MMSConfig(object): compiler.defines += ['SOURCE_ENGINE=' + sdk.code] - if sdk.name in ['sdk2013', 'bms'] and compiler.like('gcc'): + if sdk.name in ['sdk2013', 'bms'] and compiler.cxx.behavior == 'gcc': # The 2013 SDK already has these in public/tier0/basetypes.h compiler.defines.remove('stricmp=strcasecmp') compiler.defines.remove('_stricmp=strcasecmp') compiler.defines.remove('_snprintf=snprintf') compiler.defines.remove('_vsnprintf=vsnprintf') - if compiler.family == 'msvc': - compiler.defines += ['COMPILER_MSVC'] - if arch == 'x86': - compiler.defines += ['COMPILER_MSVC32'] - elif arch == 'x64': - compiler.defines += ['COMPILER_MSVC64'] - - if compiler.version >= 1900: - compiler.linkflags += ['legacy_stdio_definitions.lib'] + if compiler.cc.behavior == 'msvc': + compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32'] else: compiler.defines += ['COMPILER_GCC'] - - if arch == 'x64': - compiler.defines += ['X64BITS', 'PLATFORM_64BITS'] if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'bms', 'tf2', 'l4d', 'nucleardawn', 'l4d2', 'dota']: - if builder.target.platform in ['linux', 'mac']: + if builder.target_platform in ['linux', 'mac']: compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE'] - - if sdk.name == 'csgo' and builder.target.platform == 'linux': + + if sdk.name == 'csgo' and builder.target_platform == 'linux': compiler.linkflags += ['-lstdc++'] - + for path in paths: compiler.cxxincludes += [os.path.join(sdk.path, *path)] return compiler - def AddVersioning(self, binary, arch): - if builder.target.platform == 'windows': + def LibraryBuilder(self, compiler, name): + binary = compiler.Library(name) + if builder.target_platform == 'windows': binary.sources += ['version.rc'] binary.compiler.rcdefines += [ 'BINARY_NAME="{0}"'.format(binary.outputFile), - 'RC_COMPILE' + 'MMS_GENERATED_BUILD' ] - elif builder.target.platform == 'mac' and binary.type == 'library': + elif builder.target_platform == 'mac': binary.compiler.postlink += [ '-compatibility_version', '1.0.0', '-current_version', self.productVersion ] - if self.use_auto_versioning(): - binary.compiler.linkflags += [self.versionlib[arch]] - binary.compiler.sourcedeps += MMS.generated_headers - if builder.options.breakpad_dump: - binary.compiler.symbol_files = 'separate' - return binary - - def LibraryBuilder(self, compiler, name, arch): - binary = compiler.Library(name) - AppendArchSuffix(binary, name, arch) - self.AddVersioning(binary, arch) + binary.compiler.linkflags += [self.versionlib] + binary.compiler.sourcedeps += MMS.generated_headers return binary - def ProgramBuilder(self, compiler, name, arch): - binary = compiler.Program(name) - AppendArchSuffix(binary, name, arch) - self.AddVersioning(binary, arch) - if '-static-libgcc' in binary.compiler.linkflags: - binary.compiler.linkflags.remove('-static-libgcc') - if '-lgcc_eh' in binary.compiler.linkflags: - binary.compiler.linkflags.remove('-lgcc_eh') - if binary.compiler.like('gcc'): - binary.compiler.linkflags += ['-lstdc++'] - return binary - - def StaticLibraryBuilder(self, compiler, name, arch): - binary = compiler.StaticLibrary(name) - AppendArchSuffix(binary, name, arch) - return binary; - - def Library(self, context, name, arch): - compiler = context.cxx.clone() - SetArchFlags(compiler, arch, builder.target.platform) - return self.LibraryBuilder(compiler, name, arch) - - def Program(self, context, name, arch): - compiler = context.cxx.clone() - SetArchFlags(compiler, arch, builder.target.platform) - return self.ProgramBuilder(compiler, name, arch) - - def StaticLibrary(self, context, name, arch): - compiler = context.cxx.clone() - SetArchFlags(compiler, arch, builder.target.platform) - return self.StaticLibraryBuilder(compiler, name, arch) + def Library(self, context, name): + compiler = context.compiler.clone() + return self.LibraryBuilder(compiler, name) - def HL2Library(self, context, name, sdk, arch): - compiler = self.HL2Compiler(context, sdk, arch) - - SetArchFlags(compiler, arch, builder.target.platform) + def HL2Library(self, context, name, sdk): + compiler = self.HL2Compiler(context, sdk) - if builder.target.platform == 'linux': + if builder.target_platform == 'linux': if sdk.name == 'episode1': lib_folder = os.path.join(sdk.path, 'linux_sdk') elif sdk.name in ['sdk2013', 'bms']: lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32') - elif arch == 'x64': - lib_folder = os.path.join(sdk.path, 'lib', 'linux64') else: lib_folder = os.path.join(sdk.path, 'lib', 'linux') - elif builder.target.platform == 'mac': + elif builder.target_platform == 'mac': if sdk.name in ['sdk2013', 'bms']: lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32') - elif arch == 'x64': - lib_folder = os.path.join(sdk.path, 'lib', 'osx64') else: lib_folder = os.path.join(sdk.path, 'lib', 'mac') - if builder.target.platform in ['linux', 'mac']: - if sdk.name in ['sdk2013', 'bms'] or arch == 'x64': + if builder.target_platform in ['linux', 'mac']: + if sdk.name in ['sdk2013', 'bms']: compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'tier1.a'))] else: compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'tier1_i486.a'))] if sdk.name in ['blade', 'insurgency', 'doi', 'csgo', 'dota']: - if arch == 'x64': - compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces.a'))] - else: - compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))] - - if sdk.name == 'bms': - compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))] + compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))] + if sdk.name == 'bms': + compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))] - binary = self.LibraryBuilder(compiler, name, arch) + binary = self.LibraryBuilder(compiler, name) dynamic_libs = [] - if builder.target.platform == 'linux': + if builder.target_platform == 'linux': compiler.linkflags[0:0] = ['-lm'] if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2', 'insurgency', 'doi']: dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so'] - elif arch == 'x64' and sdk.name == 'csgo': - dynamic_libs = ['libtier0_client.so', 'libvstdlib_client.so'] elif sdk.name in ['l4d', 'blade', 'insurgency', 'doi', 'csgo', 'dota']: dynamic_libs = ['libtier0.so', 'libvstdlib.so'] else: dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so'] - elif builder.target.platform == 'mac': + elif builder.target_platform == 'mac': binary.compiler.linkflags.append('-liconv') dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib'] - elif builder.target.platform == 'windows': + elif builder.target_platform == 'windows': libs = ['tier0', 'tier1', 'vstdlib'] if sdk.name in ['swarm', 'blade', 'insurgency', 'doi', 'csgo', 'dota']: libs.append('interfaces') if sdk.name == 'bms': libs.append('mathlib') for lib in libs: - if arch == 'x86': - lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib' - elif arch == 'x64': - lib_path = os.path.join(sdk.path, 'lib', 'public', 'win64', lib) + '.lib' + lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib' binary.compiler.linkflags.append(binary.Dep(lib_path)) for library in dynamic_libs: @@ -498,31 +375,24 @@ MMS.detectProductVersion() MMS.detectSDKs() MMS.configure() -if MMS.use_auto_versioning(): - MMS.generated_headers = builder.Build( - 'support/buildbot/Versioning', - { 'MMS': MMS } - ) - MMS.versionlib = builder.Build( - 'versionlib/AMBuildScript', - { 'MMS': MMS } - ) - -BuildScripts = [ - 'loader/AMBuilder', - 'core/AMBuilder', -] -if getattr(builder.options, 'enable_tests', False): - BuildScripts += [ - 'core/sourcehook/test/AMBuilder', - ] - -if builder.backend == 'amb2': - BuildScripts += [ +MMS.generated_headers = builder.RunScript( + 'support/buildbot/Versioning', + { 'MMS': MMS } +) +MMS.versionlib = builder.RunScript( + 'versionlib/AMBuildScript', + { 'MMS': MMS } +) + +builder.RunBuildScripts( + [ + 'loader/AMBuilder', + 'core-legacy/AMBuilder', + 'core/AMBuilder', 'support/buildbot/PackageScript', - ] - -builder.Build(BuildScripts, { 'MMS': MMS }) + ], + { + 'MMS': MMS + } +) -if builder.options.breakpad_dump: - builder.Build('support/buildbot/BreakpadSymbols', { 'MMS': MMS }) diff --git a/utils/mmsource/configure.py b/utils/mmsource/configure.py index 68d3826a..3b3b313d 100644 --- a/utils/mmsource/configure.py +++ b/utils/mmsource/configure.py @@ -1,7 +1,7 @@ # vim: set sts=2 ts=8 sw=2 tw=99 et: import sys try: - from ambuild2 import run, util + from ambuild2 import run except: try: import ambuild @@ -12,23 +12,15 @@ sys.stderr.write('http://www.alliedmods.net/ambuild\n') sys.exit(1) -def make_objdir_name(p): - return 'obj-' + util.Platform() + '-' + p.target_arch - -parser = run.BuildParser(sourcePath=sys.path[0], api='2.1') -parser.default_arch = 'x86' -parser.default_build_folder = make_objdir_name -parser.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None, +run = run.PrepareBuild(sourcePath=sys.path[0]) +run.default_build_folder = 'obj-' + run.target_platform +run.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None, help='Root search folder for HL2SDKs') -parser.options.add_option('--enable-debug', action='store_const', const='1', dest='debug', +run.options.add_option('--enable-debug', action='store_const', const='1', dest='debug', help='Enable debugging symbols') -parser.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt', +run.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt', help='Enable optimization') -parser.options.add_option('-s', '--sdks', default='all', dest='sdks', +run.options.add_option('-s', '--sdks', default='all', dest='sdks', help='Build against specified SDKs; valid args are "all", "present", or ' 'comma-delimited list of engine names (default: %default)') -parser.options.add_option('--enable-tests', default=False, dest='enable_tests', action='store_true', - help='Build tests.') -parser.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump', - default=False, help='Dump and upload breakpad symbols') -parser.Configure() +run.Configure() diff --git a/utils/mmsource/core-legacy/AMBuilder b/utils/mmsource/core-legacy/AMBuilder new file mode 100644 index 00000000..6e556142 --- /dev/null +++ b/utils/mmsource/core-legacy/AMBuilder @@ -0,0 +1,20 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +import os + +if 'episode1' in MMS.sdks: + sdk = MMS.sdks['episode1'] + name = 'metamod.' + sdk.ext + binary = MMS.HL2Library(builder, name, sdk) + binary.sources += [ + 'sourcemm.cpp', + 'concommands.cpp', + 'oslink.cpp', + 'util.cpp', + 'CSmmAPI.cpp', + 'CPlugin.cpp', + 'gamedll_bridge.cpp', + 'vsp_bridge.cpp', + 'sourcehook/sourcehook.cpp', + ] + nodes = builder.Add(binary) + MMS.binaries += [nodes] diff --git a/utils/mmsource/core-legacy/CPlugin.cpp b/utils/mmsource/core-legacy/CPlugin.cpp new file mode 100644 index 00000000..b766c558 --- /dev/null +++ b/utils/mmsource/core-legacy/CPlugin.cpp @@ -0,0 +1,721 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2009 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * ============================ + */ + +#include "CPlugin.h" +#include "CSmmAPI.h" +#include "sourcemm.h" +#include "concommands.h" +#include "util.h" + +/** + * @brief Implements functions from CPlugin.h + * @file CPlugin.cpp + */ + +using namespace SourceMM; + +#define ITER_PLEVENT(evn, plid) \ + CPluginManager::CPlugin *_Xpl; \ + SourceHook::List::iterator event; \ + IMetamodListener *api; \ + for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \ + _Xpl = (*iter); \ + if (_Xpl->m_Id == plid) \ + continue; \ + for (event=_Xpl->m_Events.begin(); event!=_Xpl->m_Events.end(); event++) { \ + api = (*event).event; \ + api->evn(plid); \ + } \ + } + +CPluginManager g_PluginMngr; + +void NotifyConCommandBaseDrop(PluginId id, ConCommandBase *base) +{ + CPluginManager::CPlugin *pl; + SourceHook::List::iterator event; + IMetamodListener *api; + for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) + { + pl = (*iter); + if (pl->m_Status < Pl_Paused) + continue; + if (pl->m_API->GetApiVersion() < 11) + continue; + for (event = pl->m_Events.begin(); event != pl->m_Events.end(); event++) + { + api = (*event).event; + api->OnUnlinkConCommandBase(id, base); + } + } +} + +CPluginManager::CPluginManager() +{ + m_LastId = Pl_MinId; + m_AllLoaded = false; +} + +CPluginManager::~CPluginManager() +{ + SourceHook::List::iterator iter; + + for (iter=m_Aliases.begin(); iter!=m_Aliases.end(); iter++) + { + delete (*iter); + } + + m_Aliases.clear(); +} + +const char *CPluginManager::LookupAlias(const char *alias) +{ + SourceHook::List::iterator iter; + CNameAlias *p; + + for (iter=m_Aliases.begin(); iter!=m_Aliases.end(); iter++) + { + p = (*iter); + if (p->alias.compare(alias) == 0) + { + return p->value.c_str(); + } + } + + return NULL; +} + +SourceHook::List::iterator CPluginManager::_alias_begin() +{ + return m_Aliases.begin(); +} + +SourceHook::List::iterator CPluginManager::_alias_end() +{ + return m_Aliases.end(); +} + +void CPluginManager::SetAlias(const char *alias, const char *value) +{ + SourceHook::List::iterator iter; + CNameAlias *p; + + for (iter=m_Aliases.begin(); iter!=m_Aliases.end(); iter++) + { + p = (*iter); + if (p->alias.compare(alias) == 0) + { + if (value[0] == '\0') + { + iter = m_Aliases.erase(iter); + return; + } else { + p->value.assign(value); + return; + } + } + } + + if (value[0] != '\0') + { + p = new CNameAlias; + + p->alias.assign(alias); + p->value.assign(value); + + m_Aliases.push_back(p); + } +} + +CPluginManager::CPlugin::CPlugin() : m_Id(0), m_Source(0), m_API(NULL), m_Lib(NULL) +{ + +} + +PluginId CPluginManager::Load(const char *file, PluginId source, bool &already, char *error, size_t maxlen) +{ + already = false; + //Check if we're about to reload an old plugin + PluginIter i = m_Plugins.begin(); + while (i != m_Plugins.end()) + { + if ( (*i) && UTIL_PathCmp(file, (*i)->m_File.c_str()) ) + { + if ( (*i)->m_Status < Pl_Paused ) + { + //Attempt to load the plugin again + already = true; + i = m_Plugins.erase(i); + continue; + } else { + //No need to load it + already = true; + return (*i)->m_Id; + } + } + i++; + } + + CPlugin *pl = _Load(file, source, error, maxlen); + + if (!pl) + return Pl_BadLoad; + + ITER_PLEVENT(OnPluginLoad, pl->m_Id); + + return pl->m_Id; +} + +CPluginManager::CPlugin *CPluginManager::FindById(PluginId id) +{ + PluginIter i; + + for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++) + { + if ( (*i)->m_Id == id ) + return (*i); + } + + return NULL; +} + +void CPluginManager::SetAllLoaded() +{ + m_AllLoaded = true; + PluginIter i; + + for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++) + { + if ( (*i) && (*i)->m_Status == Pl_Running && (*i)->m_API ) + { + //API 4 is when we added this callback + //Min version is now 5, so we ignore this check + //if ( (*i)->m_API->GetApiVersion() >= 004 ) + (*i)->m_API->AllPluginsLoaded(); + } + } +} + +void CPluginManager::SetVSPAsLoaded() +{ + PluginIter i; + CPlugin *pPlugin; + SourceHook::List::iterator event; + + for (i = m_Plugins.begin(); i != m_Plugins.end(); i++) + { + pPlugin = (*i); + if (pPlugin->m_Status < Pl_Paused) + { + continue; + } + /* Only valid for plugins >= 10 (v1:5, SourceMM 1.4) */ + if (pPlugin->m_API->GetApiVersion() < 10) + { + continue; + } + for (event = pPlugin->m_Events.begin(); + event != pPlugin->m_Events.end(); + event++) + { + if ((*event).got_vsp) + { + continue; + } + (*event).got_vsp = true; + (*event).event->OnVSPListening(g_pRealVspCallbacks); + } + } +} + +bool CPluginManager::Pause(PluginId id, char *error, size_t maxlen) +{ + CPlugin *pl = FindById(id); + + if (!pl) + { + UTIL_Format(error, maxlen, "Plugin id not found"); + return false; + } + + bool ret; + + if ( (ret=_Pause(pl, error, maxlen)) == true ) + { + ITER_PLEVENT(OnPluginPause, pl->m_Id); + } + + return ret; +} + +bool CPluginManager::Unpause(PluginId id, char *error, size_t maxlen) +{ + CPlugin *pl = FindById(id); + + if (!pl) + { + UTIL_Format(error, maxlen, "Plugin id not found"); + return false; + } + + bool ret; + + if ( (ret=_Unpause(pl, error, maxlen)) == true ) + { + ITER_PLEVENT(OnPluginUnpause, pl->m_Id); + } + + return ret; +} + +bool CPluginManager::Unload(PluginId id, bool force, char *error, size_t maxlen) +{ + CPlugin *pl = FindById(id); + + if (!pl) + { + UTIL_Format(error, maxlen, "Plugin %d not found", id); + return false; + } + + bool ret; + PluginId old_id = pl->m_Id; + if ( (ret=_Unload(pl, force, error, maxlen)) == true ) + { + ITER_PLEVENT(OnPluginUnload, old_id); + } + + return ret; +} + +bool CPluginManager::Retry(PluginId id, char *error, size_t len) +{ + PluginIter i; + char buffer[64]; + for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++) + { + if ( (*i) && (*i)->m_Id == id ) + { + if ( (*i)->m_Status >= Pl_Paused) + { + UTIL_Format(error, len, "Plugin %d is already running.", id); + return false; + } + CPlugin *pl = _Load((*i)->m_File.c_str(), Pl_Console, error, len); + if (!pl) + return false; + if (pl->m_Status >= Pl_Paused) + { + //Now it gets crazy... unload the original copy. + _Unload( (*i), true, buffer, sizeof(buffer)-1 ); + + //Set the new copy's id + pl->m_Id = id; + + //We just wasted an id... reclaim it + m_LastId--; + + return true; + } else { + //don't really care about the buffer here + _Unload(pl, true, buffer, sizeof(buffer)-1); + + //We just wasted an id... reclaim it + m_LastId--; + return false; + } + } + } + + UTIL_Format(error, len, "Plugin %d not found,", id); + return false; +} + +CPluginManager::CPlugin *CPluginManager::FindByAPI(ISmmPlugin *api) +{ + PluginIter i; + + //don't find bad plugins! + if (!api) + return NULL; + + for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++) + { + if ( (*i)->m_API == api ) + return (*i); + } + + return NULL; +} + +CPluginManager::CPlugin *CPluginManager::_Load(const char *file, PluginId source, char *error, size_t maxlen) +{ + FILE *fp; + CPlugin *pl; + + pl = new CPlugin(); + *error = '\0'; + + //Add plugin to list + pl->m_Id = m_LastId; + pl->m_File.assign(file); + m_Plugins.push_back(pl); + m_LastId++; + + //Check if the file even exists + fp = fopen(file, "r"); + if (!fp) + { + if (error) + UTIL_Format(error, maxlen, "File not found: %s", file); + pl->m_Status = Pl_NotFound; + } + + if (fp) + { + fclose(fp); + fp = NULL; + + //Load the file + pl->m_Lib = dlmount(file); + if (!pl->m_Lib) + { + if (error) + UTIL_Format(error, maxlen, "[%d]", GetLastError()); + pl->m_Status = Pl_Error; + } else { + CreateInterfaceFn pfn = (CreateInterfaceFn)(dlsym(pl->m_Lib, PL_EXPOSURE_C)); + if (!pfn) + { + if (error) + UTIL_Format(error, maxlen, "Function %s not found", PL_EXPOSURE_C); + pl->m_Status = Pl_Error; + } else { + pl->m_API = static_cast((pfn)(PLAPI_NAME, NULL)); + if (!pl->m_API) + { + if (error) + UTIL_Format(error, maxlen, "Failed to get API"); + pl->m_Status = Pl_Error; + } else { + int api = pl->m_API->GetApiVersion(); + if (api < PLAPI_MIN_VERSION) + { + if (error) + UTIL_Format(error, maxlen, "Plugin API %d is out of date with required minimum (%d)", api, PLAPI_MIN_VERSION); + pl->m_Status = Pl_Error; + } else if (api > PLAPI_VERSION) { + if (error) + UTIL_Format(error, maxlen, "Plugin API %d is newer than internal version (%d)", api, PLAPI_VERSION); + pl->m_Status = Pl_Error; + } else { + if (pl->m_API->Load(pl->m_Id, static_cast(&g_SmmAPI), error, maxlen, m_AllLoaded)) + { + pl->m_Status = Pl_Running; + if (m_AllLoaded) + { + //API 4 is when we added this callback + //Removing this code as the min version is now 5 + //if (pl->m_API->GetApiVersion() >= 4) + pl->m_API->AllPluginsLoaded(); + } + if (g_bIsBridgedAsVsp) + { + SourceHook::List::iterator event; + for (event = pl->m_Events.begin(); + event != pl->m_Events.end(); + event++) + { + if (pl->m_API->GetApiVersion() < 10 || (*event).got_vsp) + continue; + (*event).got_vsp = true; + (*event).event->OnVSPListening(g_pRealVspCallbacks); + } + } + } else { + pl->m_Status = Pl_Refused; + } + } + } + } + } + } + + if (pl->m_Lib && (pl->m_Status < Pl_Paused)) + { + pl->m_Events.clear(); + g_SourceHook.UnloadPlugin(pl->m_Id); + UnregAllConCmds(pl); + + dlclose(pl->m_Lib); + pl->m_Lib = NULL; + pl->m_API = NULL; + } + + return pl; +} + +bool CPluginManager::_Unload(CPluginManager::CPlugin *pl, bool force, char *error, size_t maxlen) +{ + if (error) + *error = '\0'; + if (pl->m_API && pl->m_Lib) + { + //Note, we'll always tell the plugin it will be unloading... + if (pl->m_API->Unload(error, maxlen) || force) + { + //Make sure to detach it from sourcehook! + g_SourceHook.UnloadPlugin(pl->m_Id); + + UnregAllConCmds(pl); + + //Clean up the DLL + dlclose(pl->m_Lib); + pl->m_Lib = NULL; + pl->m_API = NULL; + + //Remove the plugin from the list + PluginIter i; + for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++) + { + if ( (*i)->m_Id == pl->m_Id ) + { + i = m_Plugins.erase(i); + break; + } + } + //Free its memory + delete pl; + + return true; + } + } else { + //The plugin is not valid, and let's just remove it from the list anyway + PluginIter i; + for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++) + { + if ( (*i)->m_Id == pl->m_Id ) + { + i = m_Plugins.erase(i); + break; + } + } + delete pl; + + return true; + } + + return false; +} + +bool CPluginManager::_Pause(CPluginManager::CPlugin *pl, char *error, size_t maxlen) +{ + if (error) + *error = '\0'; + if (pl->m_Status != Pl_Running || !pl->m_API) + { + if (error) + UTIL_Format(error, maxlen, "Plugin cannot be paused"); + } else { + if (pl->m_API->Pause(error, maxlen)) + { + g_SourceHook.PausePlugin(pl->m_Id); + pl->m_Status = Pl_Paused; + + return true; + } + } + + return false; +} + +bool CPluginManager::_Unpause(CPluginManager::CPlugin *pl, char *error, size_t maxlen) +{ + if (error) + *error = '\0'; + + if (pl->m_Status != Pl_Paused || !pl->m_API) + { + if (error) + UTIL_Format(error, maxlen, "Plugin cannot be unpaused"); + } else { + if (pl->m_API->Unpause(error, maxlen)) + { + g_SourceHook.UnpausePlugin(pl->m_Id); + pl->m_Status = Pl_Running; + + return true; + } + } + + return false; +} + +bool CPluginManager::UnloadAll() +{ + PluginIter i; + + char error[128]; + bool status = true; + + while ((i = m_Plugins.begin()) != m_Plugins.end()) + { + if ( !_Unload( (*i), true, error, sizeof(error)) ) + { + status = false; + } + } + + return status; +} + +bool CPluginManager::Query(PluginId id, const char *&file, Pl_Status &status, PluginId &source) +{ + CPlugin *pl = FindById(id); + + if (!pl) + return false; + + file = pl->m_File.c_str(); + status = pl->m_Status; + source = pl->m_Source; + + return true; +} + +bool CPluginManager::QueryRunning(PluginId id, char *error, size_t maxlength) +{ + CPlugin *pl = FindById(id); + + if (!pl || !pl->m_API) + { + if (error) + UTIL_Format(error, maxlength, "Plugin not valid"); + return false; + } + + return pl->m_API->QueryRunning(error, maxlength); +} + +bool CPluginManager::QueryHandle(PluginId id, void *&handle) +{ + CPlugin *pl = FindById(id); + + if (!pl) + { + return false; + } + + handle = static_cast(pl->m_Lib); + + return true; +} + +PluginIter CPluginManager::_begin() +{ + return m_Plugins.begin(); +} + +PluginIter CPluginManager::_end() +{ + return m_Plugins.end(); +} + +void CPluginManager::AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar) +{ + CPlugin *pl = FindByAPI(api); + + if (!pl) + return; + + pl->m_Cvars.push_back(pCvar); +} + +void CPluginManager::AddPluginCmd(ISmmPlugin *api, ConCommandBase *pCmd) +{ + CPlugin *pl = FindByAPI(api); + + if (!pl) + return; + + pl->m_Cmds.push_back(pCmd); +} + +void CPluginManager::RemovePluginCvar(ISmmPlugin *api, ConCommandBase *pCvar) +{ + CPlugin *pl = FindByAPI(api); + + if (!pl) + return; + + pl->m_Cvars.remove(pCvar); +} + +void CPluginManager::RemovePluginCmd(ISmmPlugin *api, ConCommandBase *pCmd) +{ + CPlugin *pl = FindByAPI(api); + + if (!pl) + return; + + pl->m_Cmds.remove(pCmd); +} + +void CPluginManager::UnregAllConCmds(CPlugin *pl) +{ + SourceHook::List::iterator i; + + for (i = pl->m_Cvars.begin(); i != pl->m_Cvars.end(); i++) + { + NotifyConCommandBaseDrop(pl->m_Id, (*i)); + g_SMConVarAccessor.Unregister((*i)); + } + + pl->m_Cvars.clear(); + + for (i = pl->m_Cmds.begin(); i != pl->m_Cmds.end(); i++) + { + NotifyConCommandBaseDrop(pl->m_Id, (*i)); + g_SMConVarAccessor.Unregister((*i)); + } + + pl->m_Cmds.clear(); +} + +const char *CPluginManager::GetStatusText(CPlugin *pl) +{ + switch (pl->m_Status) + { + case Pl_NotFound: + return "NOFILE"; + case Pl_Error: + return "ERROR"; + case Pl_Refused: + return "FAILED"; + case Pl_Paused: + return "PAUSED"; + case Pl_Running: + { + if (pl->m_API && pl->m_API->QueryRunning(NULL, 0)) + { + return "STOPPED"; + } else { + return "RUNNING"; + } + } + default: + return "-"; + } +} + +unsigned int CPluginManager::GetPluginCount() +{ + return (unsigned int)m_Plugins.size(); +} diff --git a/utils/mmsource/core-legacy/CPlugin.h b/utils/mmsource/core-legacy/CPlugin.h new file mode 100644 index 00000000..4e2cf91f --- /dev/null +++ b/utils/mmsource/core-legacy/CPlugin.h @@ -0,0 +1,159 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2008 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): David "BAILOPAN" Anderson +* ============================ +*/ + +#ifndef _INCLUDE_CPLUGIN_H +#define _INCLUDE_CPLUGIN_H + +/** + * @brief Implementation of Plugin API and Management routines + * @file CPlugin.cpp + */ + +#include +#include +#include "convar_smm.h" +#include "IPluginManager.h" +#include "oslink.h" +#include "sh_list.h" +#include "sh_string.h" + +/** + * History of plugin versions: (M=min, C=current) + * 1: Initial interface + * 2: Added GetLogTag() + * 3: Moved GetApiVersion() to top (2005-04-16) + * 4: Added AllPluginsLoaded() callback (2005-04-18) + * 5: Bumped version for SourceHook V4 (2005-05-01) + * 6: Added functions for console printing (2005-05-26) + * M 7: Changed template libraries (2005-08-11) + * New loading structure mechanism + * New SourceHook version + * 8: New SourceHook version (2005-12-23) + * New ISmmAPI additions + * 9: New ISmmPluginManager additions + * C 10: Added VSP listen functions to ISmmAPI and IMetamodListener (2007-02-09) + */ + +#define PLAPI_MIN_VERSION 7 + +namespace SourceMM +{ + struct CNameAlias + { + SourceHook::String alias; + SourceHook::String value; + }; + + struct CPluginEventHandler + { + bool got_vsp; + IMetamodListener *event; + }; + + /** + * @brief Implements Plugin Manager API + */ + class CPluginManager : public ISmmPluginManager + { + public: + /** + * @brief Internal structure for holding plugin data + */ + class CPlugin + { + public: + CPlugin(); + public: + PluginId m_Id; + SourceHook::String m_File; + Pl_Status m_Status; + PluginId m_Source; + ISmmPlugin *m_API; + HINSTANCE m_Lib; + SourceHook::List m_Cvars; + SourceHook::List m_Cmds; + SourceHook::List m_Events; + }; + public: + CPluginManager(); + ~CPluginManager(); + void SetAllLoaded(); + public: + PluginId Load(const char *file, PluginId source, bool &already, char *error, size_t maxlen); + bool Unload(PluginId id, bool force, char *error, size_t maxlen); + bool Pause(PluginId id, char *error, size_t maxlen); + bool Unpause(PluginId id, char *error, size_t maxlen); + bool UnloadAll(); + void SetAlias(const char *alias, const char *value); + public: + bool Query(PluginId id, const char *&file, Pl_Status &status, PluginId &source); + bool QueryRunning(PluginId id, char *error, size_t maxlength); + bool QueryHandle(PluginId id, void *&handle); + + void AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar); + void AddPluginCmd(ISmmPlugin *api, ConCommandBase *pCmd); + void RemovePluginCvar(ISmmPlugin *api, ConCommandBase *pCvar); + void RemovePluginCmd(ISmmPlugin *api, ConCommandBase *pCmd); + + /** + * @brief Finds a plugin by Id + * + * @param id Id of plugin + * @return CPlugin on success, NULL otherwise + */ + CPlugin *FindById(PluginId id); + + CPlugin *FindByAPI(ISmmPlugin *api); + + /** + * @brief Attempts to reload a failed plugin + * + * @param id Id of plugin + * @param error Error message buffer + * @param len Maximum length of buffer + * @return True on success, false otherwise + */ + bool Retry(PluginId id, char *error, size_t len); + + //get alias info + const char *LookupAlias(const char *alias); + SourceHook::List::iterator _alias_begin(); + SourceHook::List::iterator _alias_end(); + + //Internal iterators + SourceHook::List::iterator _begin(); + SourceHook::List::iterator _end(); + + void SetVSPAsLoaded(); + unsigned int GetPluginCount(); + const char *GetStatusText(CPlugin *pl); + private: + //These are identical internal functions for the wrappers above. + CPlugin *_Load(const char *file, PluginId source, char *error, size_t maxlen); + bool _Unload(CPlugin *pl, bool force, char *error, size_t maxlen); + bool _Pause(CPlugin *pl, char *error, size_t maxlen); + bool _Unpause(CPlugin *pl, char *error, size_t maxlen); + void UnregAllConCmds(CPlugin *pl); + private: + PluginId m_LastId; + SourceHook::List m_Plugins; + SourceHook::List m_Aliases; + bool m_AllLoaded; + }; +}; + +void NotifyConCommandBaseDrop(PluginId id, ConCommandBase *base); + +typedef SourceHook::List::iterator PluginIter; + +/** @brief Singleton for plugin manager */ +extern SourceMM::CPluginManager g_PluginMngr; + +#endif //_INCLUDE_CPLUGIN_H diff --git a/utils/mmsource/core-legacy/CSmmAPI.cpp b/utils/mmsource/core-legacy/CSmmAPI.cpp new file mode 100644 index 00000000..c4d7678f --- /dev/null +++ b/utils/mmsource/core-legacy/CSmmAPI.cpp @@ -0,0 +1,653 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2010 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * ============================ + */ + +#include "convar_smm.h" +#include "CSmmAPI.h" +#include "sourcemm.h" +#include "concommands.h" +#include "CPlugin.h" +#include "util.h" +#include "sh_memory.h" +#include +#if defined __linux__ +#include +#endif + +/** + * @brief Implementation of main API interface + * @file CSmmAPI.cpp + */ + +using namespace SourceMM; +using namespace SourceHook; + +struct UsrMsgInfo +{ + UsrMsgInfo() + { + } + UsrMsgInfo(int s, const char *t) : size(s), name(t) + { + } + int size; + String name; +}; + +CSmmAPI g_SmmAPI; + +static CVector usermsgs_list; +static jmp_buf usermsg_end; + +CSmmAPI::CSmmAPI() +{ + m_ConPrintf = NULL; + m_CmdCache = false; + m_VSP = false; +} + +void CSmmAPI::LogMsg(ISmmPlugin *pl, const char *msg, ...) +{ + va_list ap; + static char buffer[2048]; + + va_start(ap, msg); + UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap); + va_end(ap); + + LogMessage("[%s] %s", pl->GetLogTag(), buffer); +} + +CreateInterfaceFn CSmmAPI::engineFactory(bool syn) +{ + if (syn) + return EngineFactory; + return g_Engine.engineFactory; +} + +CreateInterfaceFn CSmmAPI::physicsFactory(bool syn) +{ + if (syn) + return PhysicsFactory; + return g_Engine.physicsFactory; +} + +CreateInterfaceFn CSmmAPI::fileSystemFactory(bool syn) +{ + if (syn) + return FileSystemFactory; + return g_Engine.fileSystemFactory; +} + +CreateInterfaceFn CSmmAPI::serverFactory(bool syn) +{ + if (syn) + return ServerFactory; + return g_GameDll.factory; +} + +CGlobalVars *CSmmAPI::pGlobals() +{ + return g_Engine.pGlobals; +} + +void CSmmAPI::SetLastMetaReturn(META_RES res) +{ + m_Res = res; +} + +META_RES CSmmAPI::GetLastMetaReturn() +{ + return m_Res; +} + +IConCommandBaseAccessor *CSmmAPI::GetCvarBaseAccessor() +{ + return static_cast(&g_SMConVarAccessor); +} + +bool CSmmAPI::RegisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) +{ + if (pCommand->IsCommand()) + { + g_PluginMngr.AddPluginCmd(plugin, pCommand); + } else { + g_PluginMngr.AddPluginCvar(plugin, pCommand); + } + + return g_SMConVarAccessor.Register(pCommand); +} + +void CSmmAPI::UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) +{ + if (pCommand->IsCommand()) + { + g_PluginMngr.RemovePluginCmd(plugin, pCommand); + } else { + g_PluginMngr.RemovePluginCvar(plugin, pCommand); + } + + CPluginManager::CPlugin *pPlugin = g_PluginMngr.FindByAPI(plugin); + PluginId id = (pPlugin != NULL) ? pPlugin->m_Id : Pl_BadLoad; + + NotifyConCommandBaseDrop(id, pCommand); + + g_SMConVarAccessor.Unregister(pCommand); +} + +void CSmmAPI::ConPrint(const char *fmt) +{ + (m_ConPrintf)("%s", fmt); +} + +void CSmmAPI::ConPrintf(const char *fmt, ...) +{ + va_list ap; + static char buffer[4096]; + + va_start(ap, fmt); + UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + (m_ConPrintf)("%s", buffer); +} + +void CSmmAPI::AddListener(ISmmPlugin *plugin, IMetamodListener *pListener) +{ + CPluginManager::CPlugin *pl = g_PluginMngr.FindByAPI(plugin); + CPluginEventHandler cpeh; + + cpeh.event = pListener; + cpeh.got_vsp = false; + + pl->m_Events.push_back(cpeh); +} + +void *CSmmAPI::MetaFactory(const char *iface, int *_ret, PluginId *id) +{ + if (id) + { + *id = 0; + } + + if (!iface) + { + return NULL; + } + + //first check ours... we get first chance! + if (strcmp(iface, MMIFACE_SOURCEHOOK) == 0) + { + if (_ret) + { + *_ret = IFACE_OK; + } + return static_cast(static_cast(&g_SourceHook)); + } else if (strcmp(iface, MMIFACE_PLMANAGER) == 0) { + if (_ret) + { + *_ret = IFACE_OK; + } + return static_cast(static_cast(&g_PluginMngr)); + } + + CPluginManager::CPlugin *pl; + SourceHook::List::iterator event; + IMetamodListener *api; + int ret = 0; + void *val = NULL; + + for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) + { + pl = (*iter); + for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) + { + api = (*event).event; + ret = IFACE_FAILED; + if ( (val=api->OnMetamodQuery(iface, &ret)) != NULL ) + { + if (_ret) + *_ret = ret; + if (id) + *id = pl->m_Id; + return val; + } + } + } + + if (_ret) + *_ret = IFACE_FAILED; + + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +//THERE BE HAX HERE!!!! DON'T TELL ALFRED, BUT GABE WANTED IT THAT WAY. // +// (note: you can find the offset by looking for the text // +// "Echo text to console", you'll find the callback cmd pushed on the // +// stack.) // +////////////////////////////////////////////////////////////////////////// + +#define SIGLEN 8 +#define ENGINE486_SIG "\x55\x89\xE5\x53\x83\xEC\x14\xBB" +#define ENGINE486_OFFS 40 +#define ENGINE686_SIG "\x53\x83\xEC\x08\xBB\x01\x00\x00" +#define ENGINE686_OFFS 50 +#define ENGINEAMD_SIG "\x53\x51\xBB\x01\x00\x00\x00\x51" +#define ENGINEAMD_OFFS 47 +#define ENGINEW32_SIG "\xA1\x2A\x2A\x2A\x2A\x56\xBE\x01" +#define ENGINEW32_OFFS 38 +#define IA32_CALL 0xE8 + +//Thanks to fysh for the idea of extracting info from "echo" and for +// having the original offsets at hand! +bool CSmmAPI::CacheCmds() +{ + ICvar *pCvar = g_Engine.icvar; + + ConCommandBase *pBase = pCvar->GetCommands(); + unsigned char *ptr = NULL; + FnCommandCallback callback = NULL; + int offs = 0; + + while (pBase) + { + if ( strcmp(pBase->GetName(), "echo") == 0 ) + { + //callback = //*((FnCommandCallback *)((char *)pBase + offsetof(ConCommand, m_fnCommandCallback))); + callback = ((ConCommand *)pBase)->GetCallback(); + ptr = (unsigned char *)callback; + #ifdef OS_LINUX + if (UTIL_VerifySignature(ptr, ENGINE486_SIG, SIGLEN)) + { + offs = ENGINE486_OFFS; + } + else if (UTIL_VerifySignature(ptr, ENGINE686_SIG, SIGLEN)) + { + offs = ENGINE686_OFFS; + } + else if (UTIL_VerifySignature(ptr, ENGINEAMD_SIG, SIGLEN)) + { + offs = ENGINEAMD_OFFS; + } + #elif defined OS_WIN32 // Only one Windows engine binary so far... + if (UTIL_VerifySignature(ptr, ENGINEW32_SIG, SIGLEN)) + { + offs = ENGINEW32_OFFS; + } + #endif + + if (!offs || ptr[offs - 1] != IA32_CALL) + { + m_ConPrintf = (CONPRINTF_FUNC)Msg; + return false; + } + //get the relative offset + m_ConPrintf = *((CONPRINTF_FUNC *)(ptr + offs)); + //add the base offset, to the ip (which is the address+offset + 4 bytes for next instruction) + m_ConPrintf = (CONPRINTF_FUNC)((unsigned long)m_ConPrintf + (unsigned long)(ptr + offs) + 4); + + m_CmdCache = true; + + return true; + } + pBase = const_cast(pBase->GetNext()); + } + + m_ConPrintf = (CONPRINTF_FUNC)Msg; + + return false; +} + +bool CSmmAPI::CmdCacheSuccessful() +{ + return m_CmdCache; +} + +void CSmmAPI::GetApiVersions(int &major, int &minor, int &plvers, int &plmin) +{ + major = SM_VERS_API_MAJOR; + minor = SM_VERS_API_MINOR; + plvers = PLAPI_VERSION; + plmin = PLAPI_MIN_VERSION; +} + +void CSmmAPI::GetShVersions(int &shvers, int &shimpl) +{ + shvers = SH_IFACE_VERSION; + shimpl = SH_IMPL_VERSION; +} + +int CSmmAPI::FormatIface(char iface[], unsigned int maxlength) +{ + int length = (int)strlen(iface); + int i; + int num = 0; + + for (i = length - 1; i >= 0; i--) + { + if (!isdigit(iface[i])) + { + if (i != length - 1) + { + num = 1; + } + break; + } + } + + if ( (num && ((int)maxlength <= length)) || (!num && ((int)maxlength <= length + 3)) ) + { + return -1; + } + + if (i != length - 1) + num = atoi(&(iface[++i])); + + num++; + + snprintf(&(iface[i]), 4, "%03d", num); + + return num; +} + +void *CSmmAPI::InterfaceSearch(CreateInterfaceFn fn, const char *iface, int max, int *ret) +{ + char _if[256]; /* assume no interface goes beyond this */ + size_t len = strlen(iface); + int num = 0; + void *pf = NULL; + + if (max > 999) + max = 999; + + if (len + 4 > sizeof(_if)) + { + if (ret) + { + *ret = IFACE_FAILED; + } + return NULL; + } + + strcpy(_if, iface); + + do + { + if ( (pf = (fn)(_if, ret)) != NULL ) + break; + if (num > max) + break; + } while (( num = FormatIface(_if, len+1) )); + + return pf; +} + +void *CSmmAPI::VInterfaceMatch(CreateInterfaceFn fn, const char *iface, int min) +{ + char buffer[256]; /* assume no interface will go beyond this */ + size_t len = strlen(iface); + int ret; /* just in case something doesn't handle NULL properly */ + + if (len > sizeof(buffer) - 4) + { + return NULL; + } + + strcpy(buffer, iface); + + if (min != -1) + { + char *ptr = &buffer[len - 1]; + int digits = 0; + while (isdigit(*ptr) && digits <=3) + { + *ptr = '\0'; + digits++; + ptr--; + } + if (digits != 3) + { + /* for now, assume this is an error */ + strcpy(buffer, iface); + } else { + char num[4]; + min = (min == 0) ? 1 : min; + snprintf(num, sizeof(num), "%03d", min); + strcat(buffer, num); + } + } + + return InterfaceSearch(fn, buffer, IFACE_MAXNUM, &ret); +} + +const char *CSmmAPI::GetBaseDir() +{ + return g_ModPath.c_str(); +} + +void CSmmAPI::PathFormat(char *buffer, size_t len, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + size_t mylen = UTIL_FormatArgs(buffer, len, fmt, ap); + va_end(ap); + + for (size_t i = 0; i < mylen; i++) + { + if (buffer[i] == ALT_SEP_CHAR) + { + buffer[i] = PATH_SEP_CHAR; + } + } +} + +void CSmmAPI::ClientConPrintf(edict_t *client, const char *fmt, ...) +{ + va_list ap; + static char buffer[4096]; + + va_start(ap, fmt); + UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + g_Engine.engine->ClientPrintf(client, buffer); +} + +void CSmmAPI::LoadAsVSP() +{ + size_t len; + char engine_file[PATH_SIZE]; + char rel_path[PATH_SIZE * 2]; + + GetFileOfAddress(g_Engine.engine, engine_file, sizeof(engine_file)); + + /* Chop off the "engine" file part */ + len = strlen(engine_file); + for (size_t i = len - 1; i < len; i--) + { + if (engine_file[i] == '/' + || engine_file[i] == '\\') + { + engine_file[i] = '\0'; + break; + } + } + + const char *usepath = g_MetamodPath.c_str(); + if (UTIL_Relatize(rel_path, sizeof(rel_path), engine_file, g_MetamodPath.c_str())) + { + usepath = rel_path; + } + + char command[PATH_SIZE * 2]; + UTIL_Format(command, sizeof(command), "plugin_load \"%s\"\n", usepath); + g_Engine.engine->ServerCommand(command); +} + +void CSmmAPI::EnableVSPListener() +{ + /* If GameInit already passed and we're not already enabled or loaded, go ahead and LoadAsVSP load */ + if (g_bGameInit && !m_VSP && !g_bIsBridgedAsVsp) + { + LoadAsVSP(); + } + m_VSP = true; +} + +int CSmmAPI::GetGameDLLVersion() +{ + return g_GameDllVersion; +} + +/* This only gets called if IServerGameDLL::GetUserMessageInfo() triggers it */ +void Detour_Error(const tchar *pMsg, ...) +{ + /* Jump back to setjmp() in CacheUserMessages() */ + longjmp(usermsg_end, 1); +} + +/* IServerGameDLL::GetUserMessageInfo() crashes on games based on the old engine and + * early Orange Box. This is because Error() from tier0 gets called when a bad index is + * passed. This is all due to a bug in CUtlRBTree::IsValidIndex(). + * + * So we detour Error() to fix this. Our detour then jumps back into CacheUserMessages() + * to a point before GetUserMessageInfo() is called. The detour is then removed and we + * exit. + */ +void CSmmAPI::CacheUserMessages() +{ + int q, size; + char buffer[256]; + unsigned char *target, *detour; + unsigned char orig_bytes[5]; + + target = (unsigned char *)&Error; + detour = (unsigned char *)&Detour_Error; + + /* Save bytes from target function */ + memcpy(orig_bytes, target, sizeof(orig_bytes)); + + /* Patch in relative jump to our Error() detour */ + SetMemAccess(target, sizeof(orig_bytes), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC); + target[0] = IA32_JMP_IMM32; + *(int32_t *)&target[1] = (int32_t)(detour - (target + 5)); + + /* This is where longjmp() will end up */ + if (setjmp(usermsg_end)) + { + /* Restore bytes and memory protection */ + memcpy(target, orig_bytes, sizeof(orig_bytes)); + SetMemAccess(target, sizeof(orig_bytes), SH_MEM_READ|SH_MEM_EXEC); + return; + } + + q = 0; + + /* If GetUserMessageInfo() calls Error(), we should end up in our detour */ + while (g_GameDll.pGameDLL->GetUserMessageInfo(q, buffer, sizeof(buffer), size)) + { + usermsgs_list.push_back(UsrMsgInfo(size, buffer)); + q++; + } + + /* Jump back to setjmp() */ + longjmp(usermsg_end, 1); +} + +int CSmmAPI::GetUserMessageCount() +{ + return (int)usermsgs_list.size(); +} + +int CSmmAPI::FindUserMessage(const char *name, int *size) +{ + for (size_t i = 0; i < usermsgs_list.size(); i++) + { + if (usermsgs_list[i].name.compare(name) == 0) + { + if (size) + { + *size = usermsgs_list[i].size; + } + return (int)i; + } + } + + return -1; +} + +const char *CSmmAPI::GetUserMessage(int index, int *size) +{ + if (index < 0 || index >= (int)usermsgs_list.size()) + { + return NULL; + } + + if (size) + { + *size = usermsgs_list[index].size; + } + + return usermsgs_list[index].name.c_str(); +} + +IServerPluginCallbacks *CSmmAPI::GetVSPInfo(int *pVersion) +{ + if (pVersion != NULL) + *pVersion = g_vsp_version; + + return g_pRealVspCallbacks; +} + +int CSmmAPI::GetSourceEngineBuild() +{ + return g_Engine.original ? SOURCE_ENGINE_ORIGINAL : SOURCE_ENGINE_EPISODEONE; +} + +void CSmmAPI::GetFullPluginPath(const char *plugin, char *buffer, size_t len) +{ + const char *pext, *ext; + + /* First find if it's an absolute path or not... */ + if (plugin[0] == '/' || strncmp(&(plugin[1]), ":\\", 2) == 0) + { + UTIL_Format(buffer, len, plugin); + return; + } + + /* Attempt to find a file extension */ + pext = UTIL_GetExtension(plugin); + /* Add an extension if there's none there */ + if (!pext) + { +#if defined WIN32 || defined _WIN32 + ext = ".dll"; +#else + ext = "_i486.so"; +#endif + } + else + { + ext = ""; + } + + /* Format the new path */ + PathFormat(buffer, len, "%s/%s%s", g_ModPath.c_str(), plugin, ext); + +#if defined __linux__ + /* If path was passed without extension and it doesn't exist with "_i486.so" try ".so" */ + struct stat s; + if (!pext && stat(buffer, &s) != 0) + { + PathFormat(buffer, len, "%s/%s.so", g_ModPath.c_str(), plugin); + } +#endif +} + diff --git a/utils/mmsource/core-legacy/CSmmAPI.h b/utils/mmsource/core-legacy/CSmmAPI.h new file mode 100644 index 00000000..5cdcff2a --- /dev/null +++ b/utils/mmsource/core-legacy/CSmmAPI.h @@ -0,0 +1,88 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2010 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * ============================ + */ + +#ifndef _INCLUDE_CSMM_API_H +#define _INCLUDE_CSMM_API_H + +/** + * @brief Header for CSmmAPI implementation + * @file CSmmAPI.h + */ + +#include "ISmmAPI.h" + +typedef void (*CONPRINTF_FUNC)(const char *, ...); + +namespace SourceMM +{ + class CSmmAPI : public ISmmAPI + { + public: + CSmmAPI(); + public: + void LogMsg(ISmmPlugin *pl, const char *msg, ...); + public: + CreateInterfaceFn engineFactory(bool syn=true); + CreateInterfaceFn physicsFactory(bool syn=true); + CreateInterfaceFn fileSystemFactory(bool syn=true); + CreateInterfaceFn serverFactory(bool syn=true); + CGlobalVars *pGlobals(); + void SetLastMetaReturn(META_RES res); + META_RES GetLastMetaReturn(); + IConCommandBaseAccessor *GetCvarBaseAccessor(); + bool RegisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand); + void UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand); + void ConPrint(const char *fmt); + void ConPrintf(const char *fmt, ...); + bool RemotePrintingAvailable() + { + return CmdCacheSuccessful(); + } + virtual void GetApiVersions(int &major, int &minor, int &plvers, int &plmin); + virtual void GetShVersions(int &shvers, int &shimpl); + virtual void AddListener(ISmmPlugin *plugin, IMetamodListener *pListener); + virtual void *MetaFactory(const char *iface, int *ret, PluginId *id); + virtual int FormatIface(char buffer[], unsigned int maxlength); + virtual void *InterfaceSearch(CreateInterfaceFn fn, const char *iface, int max, int *ret); + virtual const char *GetBaseDir(); + virtual void PathFormat(char *buffer, size_t len, const char *fmt, ...); + virtual IServerPluginCallbacks *GetVSPInfo(int *pVersion); + void ClientConPrintf(edict_t *client, const char *fmt, ...); + void *VInterfaceMatch(CreateInterfaceFn fn, const char *iface, int min=-1); + void EnableVSPListener(); + int GetGameDLLVersion(); + int GetUserMessageCount(); + int FindUserMessage(const char *name, int *size=NULL); + const char *GetUserMessage(int index, int *size=NULL); + int GetSourceEngineBuild(); + public: + bool CacheCmds(); + bool CmdCacheSuccessful(); + void LoadAsVSP(); + bool VSPEnabled() + { + return m_VSP; + } + void CacheUserMessages(); + void GetFullPluginPath(const char *plugin, char *buffer, size_t len); + private: + META_RES m_Res; + CONPRINTF_FUNC m_ConPrintf; + bool m_CmdCache; + bool m_VSP; + }; +}; + +extern SourceMM::CSmmAPI g_SmmAPI; + +#define CONMSG g_SmmAPI.ConPrintf +#define CLIENT_CONMSG g_SmmAPI.ClientConPrintf + +#endif //_INCLUDE_CSMM_API_H diff --git a/utils/mmsource/core-legacy/IPluginManager.h b/utils/mmsource/core-legacy/IPluginManager.h new file mode 100644 index 00000000..226ad619 --- /dev/null +++ b/utils/mmsource/core-legacy/IPluginManager.h @@ -0,0 +1,137 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2008 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): David "BAILOPAN" Anderson +* ============================ +*/ + +#ifndef _INCLUDE_PLUGINMANAGER_H +#define _INCLUDE_PLUGINMANAGER_H + +/** + * @brief Plugin Manager interface + * @file IPluginManager.h + */ + +typedef int PluginId; + +#include "ISmmPlugin.h" + +/** + * @brief Load sources + */ +enum +{ + Pl_BadLoad=0, + Pl_Console=-1, + Pl_File=-2, + Pl_MinId=1, +}; + +/** + * @brief Status of a plugin at runtime + */ +enum Pl_Status +{ + Pl_NotFound=-4, + Pl_Error=-3, + Pl_Refused=-2, + Pl_Paused=-1, + Pl_Running=0, +}; + +typedef int PluginId; +struct factories; + +class ISmmPluginManager +{ +public: + /** + * @brief Loads a plugin and returns its id. If this is called before DLLInit(), + * then the plugin is considered to be "hot" - it might refuse its own load later! + * Also, a hot plugin might not have an error message. + * + * @param file String containing file name + * @param source Specifies who loaded the plugin + * @param status Status of the plugin + * @param ismm Pointer to Smm API + * @param error String buffer for error messages + * @param maxlen Maximum length of buffer + * @return Id of plugin + */ + virtual PluginId Load(const char *file, PluginId source, bool &already, char *error, size_t maxlen) =0; + + /** + * @brief Unloads a plugin + * + * @param id Id of plugin + * @param error String buffer for error messages + * @param maxlen Maximum length of buffer + * @return True on success, false otherwise + */ + virtual bool Unload(PluginId id, bool force, char *error, size_t maxlen) =0; + + /** + * @brief Pauses a plugin + * + * @param id Id of plugin + * @param error String buffer for error messages + * @param maxlen Maximum length of buffer + * @return True on success, false otherwise + */ + virtual bool Pause(PluginId id, char *error, size_t maxlen) =0; + + /** + * @brief Unpauses a plugin + * + * @param id Id of plugin + * @param force If true, forces the plugin to unload + * @param error String buffer for error messages + * @param maxlen Maximum length of buffer + * @return True on success, false otherwise + */ + virtual bool Unpause(PluginId id, char *error, size_t maxlen) =0; + + /** + * @brief Unloads all plugins forcefully + * + * @return True on success, false otherwise + */ + virtual bool UnloadAll() =0; + + /** + * @brief Returns information about a plugin + * + * @param id Id of plugin + * @param file Pointer to file string by reference + * @param list Pointer to factories by reference + * @param status By reference status of plugin + * @param source By reference source of plugin + * @return True on success, false if not found + */ + virtual bool Query(PluginId id, const char *&file, Pl_Status &status, PluginId &source) =0; + + /** + * @brief Checks another plugin's QueryRunning() status. + * + * @param id Id of plugin + * @param error Message buffer + * @param maxlen Size of error buffer + * @return Status value + */ + virtual bool QueryRunning(PluginId id, char *error, size_t maxlength) =0; + + /** + * @brief Returns the handle of a plugin (OS dependent meaning) + * + * @param id Id of plugin + * @param handle By reference handle of plugin, if any + * @return True if plugin id is valid, false otherwise + */ + virtual bool QueryHandle(PluginId id, void *&handle) =0; +}; + +#endif //_INCLUDE_PLUGINMANAGER_H diff --git a/utils/mmsource/core-legacy/ISmmAPI.h b/utils/mmsource/core-legacy/ISmmAPI.h new file mode 100644 index 00000000..e56af16c --- /dev/null +++ b/utils/mmsource/core-legacy/ISmmAPI.h @@ -0,0 +1,349 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2008 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): David "BAILOPAN" Anderson +* ============================ +*/ + +#ifndef _INCLUDE_ISMM_API_H +#define _INCLUDE_ISMM_API_H + +/** + * @brief External API interface + * @file ISmmAPI.h + */ + +#include +#include +#include +#include "IPluginManager.h" + +#if defined __GNUC__ +#if ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)) || (__GNUC__ < 3) +#error "You must compile with at least GCC 3.4! If you know what you are doing, you can remove this message." +#endif //version check +#endif //__GNUC__ + +class IMetamodListener; +class ISmmPluginManager; +class ISmmPlugin; + +#define MMIFACE_SOURCEHOOK "ISourceHook" /**< ISourceHook Pointer */ +#define MMIFACE_PLMANAGER "IPluginManager" /**< SourceMM Plugin Functions */ +#define IFACE_MAXNUM 999 + +#define SOURCE_ENGINE_UNKNOWN 0 /**< Could not determine the engine version */ +#define SOURCE_ENGINE_ORIGINAL 1 /**< Original Source Engine (used by The Ship) */ +#define SOURCE_ENGINE_EPISODEONE 2 /**< Episode 1 Source Engine (second major SDK) */ + +class ISmmAPI +{ +public: + /** + * @brief Logs a message through the HL2 log system. + * Note: Newlines are appended automatically. + * + * @param pl Plugin API pointer (used for tagging message) + * @param msg Formatted string. + */ + virtual void LogMsg(ISmmPlugin *pl, const char *msg, ...) =0; +public: + /** + * @brief Returns an interface factory for the HL2 engine. + * + * @param syn If syn is true, the synthetic wrapper is returned. + * If syn is false, the true function is returned. + * @return CreateInterfaceFn function pointer. + */ + virtual CreateInterfaceFn engineFactory(bool syn=true) =0; + + /** + * @brief Returns an interface factory for the HL2 physics engine. + * + * @param syn If syn is true, the synthetic wrapper is returned. + * If syn is false, the true function is returned. + * @return CreateInterfaceFn function pointer. + */ + virtual CreateInterfaceFn physicsFactory(bool syn=true) =0; + + /** + * @brief Returns an interface factory for the HL2 file system. + * + * @param syn If syn is true, the synthetic wrapper is returned. + * If syn is false, the true function is returned. + * @return CreateInterfaceFn function pointer. + */ + virtual CreateInterfaceFn fileSystemFactory(bool syn=true) =0; + + /** + * @brief Returns an interface factory for the GameDLL. + * + * @param syn If syn is true, the synthetic wrapper is returned. + * If syn is false, the true function is returned. + * @return CreateInterfaceFn function pointer. + */ + virtual CreateInterfaceFn serverFactory(bool syn=true) =0; + + /** + * @brief Returns a CGlobalVars pointer from the HL2 Engine. + * + * @return CGlobalVars pointer. + */ + virtual CGlobalVars *pGlobals() =0; + + /** + * @brief Used with SourceHook, sets teh last meta return value. + * Note: Do not call this directly, use the Metamod macros. + * + * @param res META_RETURN value to set. + */ + virtual void SetLastMetaReturn(META_RES res) =0; + + /** + * @brief Used with SourceHook, returns the last meta return value. + * Note: This is only valid inside a hook function. + * + * @return Last META_RETURN value set by a plugin. + */ + virtual META_RES GetLastMetaReturn() =0; + +public: // Added in 1.00-RC2 (0:0) + /** + * @brief Allows access to Metamod's ConCommandBaseAccessor. + * + * @return Returns IConCommandBaseAccessor pointer. + */ + virtual IConCommandBaseAccessor *GetCvarBaseAccessor() =0; + + /** + * @brief Registers a ConCommandBase. + * + * @param plugin Parent plugin API pointer. + * @param pCommand ConCommandBase to register. + * @return True if successful, false otherwise. Does not return false yet. + */ + virtual bool RegisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) =0; + + /** + * @brief Unregisters a ConCommandBase. + * + * @param plugin Parent plugin API pointer. + * @param pCommand ConCommandBase to unlink. + */ + virtual void UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) =0; + + /** + * @brief Prints an unformatted string to the remote server console. + * Note: Newlines are not added automatically. + * + * @param str Message string. + */ + virtual void ConPrint(const char *str) =0; + + /** + * @brief Prints a formatted message to the remote server console. + * Note: Newlines are not added automatically. + * + * @param fmt Formatted message. + */ + virtual void ConPrintf(const char *fmt, ...) =0; + +public: // Added in 1.1.0 (1:0) + /** + * @brief Checks if ConPrint/ConPrintf will mirror to rcon. + * + * @return True if remote printing available, false otherwise. + */ + virtual bool RemotePrintingAvailable() =0; + + /** + * @brief Returns the Metamod Version numbers as major version and minor (API) version. + * Changes to minor version are guaranteed to be backwards compatible. + * Changes to major version are not. + * + * @param major Filled with the major API version number. + * @param minor Filled with the minor API version number. + * @param plvers Filled with the current plugin API version number. + * @param plmin Filled with the minimum plugin API version number supported. + */ + virtual void GetApiVersions(int &major, int &minor, int &plvers, int &plmin) =0; + + /** + * @brief Returns sourcehook API version and implementation version. + * + * @param shvers Filled with the SourceHook API version number. + * @param shimpl Filled with the SourceHook implementation number. + */ + virtual void GetShVersions(int &shvers, int &shimpl) =0; + + /** + * @brief Adds a Metamod listener. + * + * @param plugin Plugin interface pointer. + * @param pListener Listener interface pointer to add. + */ + virtual void AddListener(ISmmPlugin *plugin, IMetamodListener *pListener) =0; + + /** + * @brief Queries the metamod factory + * + * @param iface String containing interface name + * @param ret Optional pointer to store return status + * @param id Optional pointer to store id of plugin that overrode interface, 0 if none + * @return Returned pointer + */ + virtual void *MetaFactory(const char *iface, int *ret, PluginId *id) =0; + +public: // Added in 1.1.2 (1:1) + /** + * @brief Given a base interface name, such as ServerGameDLL or ServerGameDLL003, + * reformats the string to increase the number, then returns the new number. + * This is the base function to InterfaceSearch() and VInterfaceMatch(). + * + * @param iface Input/output interface name. Must be writable. + * @param maxlength Maximum length of iface buffer. Must be at least strlen(iface)+4 chars. + * @return The newly incremented iface version number. + */ + virtual int FormatIface(char iface[], unsigned int maxlength) =0; + +public: // Added in 1.2 (1:2) + /** + * @brief Searches for an interface for you. + * + * @param fn InterfaceFactory function. + * @param iface Interface string name. + * @param max Maximum version to look up. + * @param ret Last return code from interface factory function. + * @return Interface pointer, or NULL if not found. + */ + virtual void *InterfaceSearch(CreateInterfaceFn fn, const char *iface, int max, int *ret) =0; + + /** + * @brief Returns the base directory of the game/server, equivalent to + * IVEngineServer::GetGameDir(), except the path is absolute. + * + * @return Static pointer to game's absolute basedir. + */ + virtual const char *GetBaseDir() =0; + + /** + * @brief Formats a file path to the local OS. Does not include any base directories. + * Note that all slashes and black slashes are reverted to the local OS's expectancy. + * + * @param buffer Destination buffer to store path. + * @param len Maximum length of buffer, including null terminator. + * @param fmt Formatted string. + */ + virtual void PathFormat(char *buffer, size_t len, const char *fmt, ...) =0; + +public: // Added in 1.2.2 (1:3) + /** + * @brief Prints text in the specified client's console. Same as IVEngineServer::ClientPrintf + * except that it allows for string formatting. + * + * @param client Client edict pointer. + * @param fmt Formatted string to print to the client. + */ + virtual void ClientConPrintf(edict_t *client, const char *fmt, ...) =0; + +public: // Added in 1.3 (1:4) + /** + * @brief Wrapper around InterfaceSearch(). Assumes no maximum. + * This is designed to replace the fact that searches only went upwards. + * The "V" is intended to convey that this is for Valve formatted interface strings. + * + * @param fn Interface factory function. + * @param iface Interface string. + * @param min Minimum value to search from. If zero, searching begins from the + * first available version regardless of the interface. + * Note that this can return interfaces EARLIER than the version specified. + * A value of -1 (default) specifies the string version as the minimum. + * Any other value specifices the minimum value to search from. + * @return Interface pointer, or NULL if not found. + */ + virtual void *VInterfaceMatch(CreateInterfaceFn fn, const char *iface, int min=-1) =0; + +public: // Added in 1.4 (1:5) + /** + * @brief Tells SourceMM to add VSP hooking capability to plugins. + * + * Since this potentially uses more resources than it would otherwise, plugins have to + * explicitly enable the feature. Whether requested or not, if it is enabled, all plugins + * will get a pointer to the VSP listener through IMetamodListener. + */ + virtual void EnableVSPListener() =0; + + /** + * @brief Returns the interface version of the GameDLL's IServerGameDLL implementation. + * + * @return Interface version of the loaded IServerGameDLL. + */ + virtual int GetGameDLLVersion() =0; + + /** + * @brief Returns the number of user messages in the GameDLL. + * + * @return Number of user messages, or -1 if SourceMM has failed to get user message list. + */ + virtual int GetUserMessageCount() =0; + + /** + * @brief Returns the index of the specified user message. + * + * @param name User message name. + * @param size Optional pointer to store size of user message. + * @return Message index, or -1 on failure. + */ + virtual int FindUserMessage(const char *name, int *size=NULL) =0; + + /** + * @brief Returns the name of the specified user message. + * + * @param index User message index. + * @param size Optional pointer to store size of user message. + * @return Message name, or NULL on failure. + */ + virtual const char *GetUserMessage(int index, int *size=NULL) =0; + + /** + * @brief Returns the VSP listener loaded. + * + * This is useful for late-loading plugins which need to decide whether + * to add a listener or not (or need to get the pointer at all). + * + * @param pVersion Optional pointer to store the VSP version. + * @return IServerPluginCallbacks pointer, or NULL if an + * IMetamodListener event has yet to occur for + * EnableVSPListener(). + */ + virtual IServerPluginCallbacks *GetVSPInfo(int *pVersion) =0; + + /** + * @brief Returns the engine interface that MM:S is using as a backend. + * + * The values will be one of the SOURCE_ENGINE_* constants from the top + * of this file. + * + * @return A SOURCE_ENGINE_* constant value. + */ + virtual int GetSourceEngineBuild() =0; + +}; + + +/** + * Version History + * + * 1.1.0 Bumped API to 1:0. The breaking changes occurred in SourceHook and the plugin API. + * 1.1.2 Added API call for generating iface names. + * 1.2 Added API more helper functions and new SourceHook version. + * 1.2.2 Added API for printing to client console (with string formatting). + * 1.3 Added new interface search API. + * 1.4 Added VSP listener and user message API. + * 1.8 Backported SH VP hooks and various "new API" calls. + */ + +#endif //_INCLUDE_ISMM_API_H diff --git a/utils/mmsource/core-legacy/ISmmPlugin.h b/utils/mmsource/core-legacy/ISmmPlugin.h new file mode 100644 index 00000000..533a7ba8 --- /dev/null +++ b/utils/mmsource/core-legacy/ISmmPlugin.h @@ -0,0 +1,430 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2008 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): David "BAILOPAN" Anderson +* ============================ +*/ + +#ifndef _INCLUDE_ISMM_PLUGIN_H +#define _INCLUDE_ISMM_PLUGIN_H + +/** + * @brief Plugin API interface + * @file ISmmPlugin.h + */ + +#include +#include +#include "ISmmAPI.h" + +#define PLAPI_VERSION 11 +#define PLAPI_NAME "ISmmPlugin" + +class ISmmAPI; + +// Interface return status, binary-compatible with HL2SDK's IFACE_OK and IFACE_FAILED. +enum +{ + META_IFACE_OK = 0, + META_IFACE_FAILED +}; + +class ISmmPlugin +{ +public: + virtual int GetApiVersion() { return PLAPI_VERSION; } + virtual ~ISmmPlugin() { } +public: + /** + * @brief Called on plugin load. + * NOTE - As of API 7, this is called as DLLInit() executes - after the parameters are known, but before + * the original GameDLL function is called. Therefore, you cannot hook it, but you don't need to - + * Load() is basically your hook. + * NOTE - As of API 7, you can override factories before the engine and gamedll exchange them. + * However, take care to note that if your plugin is unloaded, and the gamedll/engine have cached + * an interface you've passed, something will definitely crash. Be careful. + * + * @param id Internal id of plugin. Saved globally by PLUGIN_SAVEVARS() + * @param ismm External API for SourceMM. Saved globally by PLUGIN_SAVEVARS() + * @param list Contains a list of factories. Hook a factory call by setting one equal to your own function. + * @param late Set to true if your plugin was loaded late (not at server load). + * @param error Error message buffer + * @param maxlen Size of error message buffer + * @return True if successful, return false to reject the load. + */ + virtual bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlength, bool late) =0; + + /** + * @brief Called when your plugin is "queried". This is useful for rejecting a loaded + * state. For example, if your plugin wants to stop operating, it can simply return + * false and copy an error message. This will notify other plugins or MM:S of something + * bad that happened. NOTE - MM:S will not cache the return state, so if you return false, + * your plugin will not actually be paused or unloaded. This callback will be called when: + * - Another plugin requests it + * - Someone types "meta list", it will show up as "REFUSED" + * - When Metamod need to re-check the plugin's status + * - If the plugin does something like overload a factory, Metamod will make sure the Query() returns true + * before calling it. + * Also note that this query will only override Metamod when the plugin is running and not paused. + * + * @param error Buffer for error message. This can be NULL! + * @param maxlen Maximum length of error buffer. + * @return Status code - true for okay, false for badness. + */ + virtual bool QueryRunning(char *error, size_t maxlen) + { + return true; + } + + /** + * @brief Called on plugin unload. You can return false if you know your plugin + * is not capable of restoring critical states it modifies. + * + * @param error Error message buffer + * @param maxlen Size of error message buffer + * @return True on success, return false to request no unload. + */ + virtual bool Unload(char *error, size_t maxlen) + { + return true; + } + + /** @brief Called on plugin pause. + * + * @param error Error message buffer + * @param maxlen Size of error message buffer + * @return True on success, return false to request no pause. + */ + virtual bool Pause(char *error, size_t maxlen) + { + return true; + } + + /** @brief Called on plugin unpause. + * + * @param error Error message buffer + * @param maxlen Size of error message buffer + * @return True on success, return false to request no unpause. + */ + virtual bool Unpause(char *error, size_t maxlen) + { + return true; + } +public: + /** @brief Return author as string */ + virtual const char *GetAuthor() =0; + + /** @brief Return plugin name as string */ + virtual const char *GetName() =0; + + /** @brief Return a description as string */ + virtual const char *GetDescription() =0; + + /** @brief Return a URL as string */ + virtual const char *GetURL() =0; + + /** @brief Return quick license code as string */ + virtual const char *GetLicense() =0; + + /** @brief Return version as string */ + virtual const char *GetVersion() =0; + + /** @brief Return author as string */ + virtual const char *GetDate() =0; + + /** @brief Return author as string */ + virtual const char *GetLogTag() =0; +public: + /** + * @brief Called when all plugins have been loaded - API version 4 + * + * This is useful for knowing when it's safe to request things another plugin might have. + * NOTE for API 7 - This is called after DLLInit(). + */ + virtual void AllPluginsLoaded() + { + } +}; + +/** + * @brief Added in 1.1 so plugins could listen to specific events + */ +class IMetamodListener +{ +public: + virtual ~IMetamodListener() { } +public: + /** + * @brief Called when a plugin is loaded. + * + * @param id Id of the plugin. + */ + virtual void OnPluginLoad(PluginId id) { } + + /** + * @brief Called when a plugin is unloaded. + * + * @param id Id of the plugin. + */ + virtual void OnPluginUnload(PluginId id) { } + + /** + * @brief Called when a plugin is paused. + * + * @param id Id of the plugin. + */ + virtual void OnPluginPause(PluginId id) { } + + /** + * @brief Called when a plugin is unpaused. + * + * @param id Id of the plugin. + */ + virtual void OnPluginUnpause(PluginId id) { } + + /** + * @brief Called when the level is loaded (after GameInit, before ServerActivate). + * + * To override this, hook IServerGameDLL::LevelInit(). + * + * @param pMapName Name of the map. + * @param pMapEntities Lump string of the map entities, in KeyValue format. + * @param pOldLevel Unknown. + * @param pLandmarkName Unknown. + * @param loadGame Unknown. + * @param background Unknown. + */ + virtual void OnLevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) { } + + /** + * @brief Called when the level is shut down. May be called more than once. + */ + virtual void OnLevelShutdown() { } + + /** + * @brief Called when engineFactory() is used through Metamod:Source's wrapper. + * This can be used to provide interfaces to other plugins or the GameDLL. + * + * If ret is passed, you should fill it with IFACE_OK or IFACE_FAILED. + * + * @param iface Interface string. + * @param ret Optional pointer to store return code. + * @return Generic pointer to the interface, or NULL if not found. + */ + virtual void *OnEngineQuery(const char *iface, int *ret) + { + if (ret) + { + *ret = IFACE_FAILED; + } + + return NULL; + } + + /** + * @brief Called when the physics factory is used through Metamod:Source's wrapper. + * This can be used to provide interfaces to other plugins. + * + * If ret is passed, you should fill it with IFACE_OK or IFACE_FAILED. + * + * @param iface Interface string. + * @param ret Optional pointer to store return code. + * @return Generic pointer to the interface, or NULL if not found. + */ + virtual void *OnPhysicsQuery(const char *iface, int *ret) + { + if (ret) + { + *ret = IFACE_FAILED; + } + + return NULL; + } + + /** + * @brief Called when the filesystem factory is used through Metamod:Source's wrapper. + * This can be used to provide interfaces to other plugins. + * + * If ret is passed, you should fill it with IFACE_OK or IFACE_FAILED. + * + * @param iface Interface string. + * @param ret Optional pointer to store return code. + * @return Generic pointer to the interface, or NULL if not found. + */ + virtual void *OnFileSystemQuery(const char *iface, int *ret) + { + if (ret) + { + *ret = IFACE_FAILED; + } + + return NULL; + } + + /** + * @brief Called when the server DLL's factory is used through Metamod:Source's wrapper. + * This can be used to provide interfaces to other plugins. + * + * If ret is passed, you should fill it with IFACE_OK or IFACE_FAILED. + * + * @param iface Interface string. + * @param ret Optional pointer to store return code. + * @return Generic pointer to the interface, or NULL if not found. + */ + virtual void *OnGameDLLQuery(const char *iface, int *ret) + { + if (ret) + { + *ret = IFACE_FAILED; + } + + return NULL; + } + + /** + * @brief Called when Metamod's own factory is invoked. + * This can be used to provide interfaces to other plugins. + * + * If ret is passed, you should fill it with IFACE_OK or IFACE_FAILED. + * + * @param iface Interface string. + * @param ret Optional pointer to store return code. + * @return Generic pointer to the interface, or NULL if not found. + */ + virtual void *OnMetamodQuery(const char *iface, int *ret) + { + if (ret) + { + *ret = IFACE_FAILED; + } + + return NULL; + } + + /** + * @brief Called when Metamod:Source acquires a valid IServerPluginCallbacks + * pointer to be used for hooking by plugins. + * + * This will only be called after a call to ISmmAPI::EnableVSPListener(). + * If called before GameInit, this callback will occur before LevelInit. + * Otherwise, it will be called on the first call after that. + * + * This callback is provided to all plugins regardless of which (or how many) + * called EnableVSPListener(), but only if at least one did in fact enable it. + * + * This callback is only available for plugins using API v1:5 (SourceMM 1.4+). + * + * @param iface Interface pointer. If NULL, then the VSP listening construct + * failed to initialize and is not available. + */ + virtual void OnVSPListening(IServerPluginCallbacks *iface) + { + } + + /** + * @brief Called when Metamod:Source knows that a specific ConCommandBase is + * about to be unregistered. This is only called for ConCommandBases + * registered by Metamod:Source plugins. + * + * This is only invoked on Metamod:Source 1.8 or higher (PLAPI_VERSION >= 11). + * + * @param plugin Plugin owning the ConCommandBase. + * @param base ConCommandBase that is being unlinked. + */ + virtual void OnUnlinkConCommandBase(PluginId id, ConCommandBase *base) + { + } +}; + +#define PL_EXPOSURE CreateInterface +#define PL_EXPOSURE_C "CreateInterface" + +#define PLUGIN_EXPOSE(name, var) \ + ISmmAPI *g_SMAPI = NULL; \ + ISmmPlugin *g_PLAPI = NULL; \ + PluginId g_PLID = (PluginId)0; \ + SourceHook::ISourceHook *g_SHPtr = NULL; \ + SMM_API void *PL_EXPOSURE(const char *name, int *code) { \ + if (name && !strcmp(name, PLAPI_NAME)) { \ + return static_cast(&var); \ + } \ + return NULL; \ + } + +#define PLUGIN_GLOBALVARS() \ + extern SourceHook::ISourceHook *g_SHPtr; \ + extern ISmmAPI *g_SMAPI; \ + extern ISmmPlugin *g_PLAPI; \ + extern PluginId g_PLID; + +#define PLUGIN_SAVEVARS() \ + g_SMAPI = ismm; \ + g_SHPtr = static_cast(ismm->MetaFactory(MMIFACE_SOURCEHOOK, NULL, NULL)); \ + g_PLAPI = static_cast(this); \ + g_PLID = id; + +#define META_LOG g_SMAPI->LogMsg +#define META_REGCMD(name) g_SMAPI->RegisterConCmdBase(g_PLAPI, name##_command) +#define META_REGCVAR(var) g_SMAPI->RegisterConCmdBase(g_PLAPI, var) +#define META_UNREGCMD(name) g_SMAPI->UnregisterConCmdBase(g_PLAPI, name##_command) +#define META_UNREGCVAR(var) g_SMAPI->UnregisterConCmdBase(g_PLAPI, var) +#define META_CONPRINT g_SMAPI->ConPrint +#define META_CONPRINTF g_SMAPI->ConPrintf + +/* Probably should use this up above someday */ +#define CONCMD_VARNAME(name) name##_command + +#if !defined SMM_API +#if defined __WIN32__ || defined _WIN32 || defined WIN32 + #define SMM_API extern "C" __declspec(dllexport) +#elif defined __GNUC__ + #if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 1) + #define SMM_API extern "C" __attribute__ ((visibility("default"))) + #else + #define SMM_API extern "C" + #endif +#endif +#endif //!defined SMM_API + +/** + * @brief Macro for automatically getting a current or newer Valve interface. + * + * @param v_factory Factory method to use from ISmmAPI (such as engineFactory). + * @param v_var Variable name to store into. + * @param v_type Interface type (do not include the pointer/asterisk). + * @param v_name Interface name. + */ +#define GET_V_IFACE_CURRENT(v_factory, v_var, v_type, v_name) \ + v_var = (v_type *)ismm->VInterfaceMatch(ismm->v_factory(), v_name); \ + if (!v_var) \ + { \ + if (error && maxlen) \ + { \ + snprintf(error, maxlen, "Could not find interface: %s", v_name); \ + } \ + return false; \ + } + + /** + * @brief Same as GET_V_IFACE, except searches for any. + * + * @param v_factory Factory method to use from ISmmAPI (such as engineFactory). + * @param v_var Variable name to store into. + * @param v_type Interface type (do not include the pointer/asterisk). + * @param v_name Interface name. + */ +#define GET_V_IFACE_ANY(v_factory, v_var, v_type, v_name) \ + v_var = (v_type *)ismm->VInterfaceMatch(ismm->v_factory(), v_name, 0); \ + if (!v_var) \ + { \ + if (error && maxlen) \ + { \ + snprintf(error, maxlen, "Could not find interface: %s", v_name); \ + } \ + return false; \ + } + +#endif //_INCLUDE_ISMM_PLUGIN_H diff --git a/utils/mmsource/core-legacy/Makefile b/utils/mmsource/core-legacy/Makefile new file mode 100644 index 00000000..733d05db --- /dev/null +++ b/utils/mmsource/core-legacy/Makefile @@ -0,0 +1,79 @@ +#(C)2004-2008 SourceMM Development Team +# Makefile written by David "BAILOPAN" Anderson + +HL2SDK = ../../hl2sdk +SRCDS = ~/srcds + +### EDIT BELOW FOR OTHER PROJECTS ### + +OPT_FLAGS = -O2 -funroll-loops -pipe -fno-strict-aliasing +GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden +DEBUG_FLAGS = -g -ggdb3 +CPP = gcc-4.1 +BINARY = metamod.1.ep1.so + +HL2PUB = $(HL2SDK)/public +HL2LIB = $(HL2SDK)/linux_sdk + +OBJECTS = oslink.cpp \ + util.cpp \ + concommands.cpp \ + CSmmAPI.cpp \ + sourcemm.cpp \ + CPlugin.cpp \ + vsp_bridge.cpp \ + gamedll_bridge.cpp \ + sourcehook/sourcehook.cpp + +LINK = $(HL2LIB)/tier1_i486.a vstdlib_i486.so tier0_i486.so -static-libgcc + +INCLUDE = -I. -I$(HL2PUB) -I$(HL2PUB)/dlls -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \ + -I$(HL2PUB)/vstdlib -I$(HL2SDK)/tier1 -I. -Isourcehook -I../loader + +ifeq "$(DEBUG)" "true" + BIN_DIR = Debug + CFLAGS += $(DEBUG_FLAGS) +else + BIN_DIR = Release + CFLAGS += $(OPT_FLAGS) +endif + +GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1) + +CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \ + -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \ + -Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Wno-uninitialized -Werror -fPIC \ + -fno-exceptions -fno-rtti -msse -m32 + +ifeq "$(GCC_VERSION)" "4" + CFLAGS += $(GCC4_FLAGS) +endif + +OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) + +$(BIN_DIR)/%.o: %.cpp + $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< + +all: + mkdir -p $(BIN_DIR)/sourcehook + mkdir -p $(BIN_DIR) + ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so + ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so + $(MAKE) sourcemm + rm -rf $(BINARY) + +sourcemm: $(OBJ_LINUX) + $(CPP) $(INCLUDE) -m32 $(CFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY) + +debug: + $(MAKE) all DEBUG=true + +default: all + +clean: + rm -rf Release/sourcehook/*.o + rm -rf Release/*.o + rm -rf Release/$(BINARY) + rm -rf Debug/sourcehook/*.o + rm -rf Debug/*.o + rm -rf Debug/$(BINARY) diff --git a/utils/mmsource/core-legacy/concommands.cpp b/utils/mmsource/core-legacy/concommands.cpp new file mode 100644 index 00000000..56fe1078 --- /dev/null +++ b/utils/mmsource/core-legacy/concommands.cpp @@ -0,0 +1,793 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2010 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * ============================ + */ + +#include +#include "convar_smm.h" +#include "CSmmAPI.h" +#include "concommands.h" +#include "CPlugin.h" +#include "sh_string.h" +#include "sh_list.h" +#include "util.h" +#include + +/** + * @brief Console Command Implementations + * @file concommands.cpp + */ + +SMConVarAccessor g_SMConVarAccessor; + +SMConVarAccessor::SMConVarAccessor() +{ + m_TopConCommandBase = NULL; +} + +bool SMConVarAccessor::RegisterConCommandBase(ConCommandBase *pCommand) +{ + /* Add the FCVAR_GAMEDLL flag + * => No crash on exit! + * UPDATE: Do _not_ add the FCVAR_GAMEDLL flag here, as it + * causes the command to be unusable on listen servers until you load a map + * We will set the FCVAR_GAMEDLL flag on all commands we have registered once we are being unloaded + */ + // pCommand->AddFlags(FCVAR_GAMEDLL); + m_RegisteredCommands.push_back(pCommand); + + pCommand->SetNext(NULL); + g_Engine.icvar->RegisterConCommandBase(pCommand); + + return true; +} + +bool SMConVarAccessor::Register(ConCommandBase *pCommand) +{ + /* Simple, don't mark as part of sourcemm! */ + pCommand->SetNext(NULL); + g_Engine.icvar->RegisterConCommandBase(pCommand); + + return true; +} + +void SMConVarAccessor::MarkCommandsAsGameDLL() +{ + for (SourceHook::List::iterator iter = m_RegisteredCommands.begin(); + iter != m_RegisteredCommands.end(); ++iter) + { + (*iter)->AddFlags(FCVAR_GAMEDLL); + } +} + +void SMConVarAccessor::Unregister(ConCommandBase *pCommand) +{ + ConCommandBase *pCur = NULL; + ConCommandBase *pPrev = NULL; + + if (!pCommand || !pCommand->IsRegistered()) + { + return; + } + + pCur = g_Engine.icvar->GetCommands(); + pCommand->SetRegistered(false); + + if (!m_TopConCommandBase || !pCur) + { + return; + } + + if (pCur == pCommand) + { + *m_TopConCommandBase = const_cast(pCommand->GetNext()); + pCommand->SetNext(NULL); + return; + } + + pPrev = pCur; + pCur = const_cast(pCur->GetNext()); + + while (pCur) + { + if (pCur == pCommand) + { + pPrev->SetNext(const_cast(pCommand->GetNext())); + pCommand->SetNext(NULL); + } + + pPrev = pCur; + pCur = const_cast(pCur->GetNext()); + } +} + +ConVar metamod_version("metamod_version", METAMOD_VERSION, FCVAR_SPONLY | FCVAR_NOTIFY, "Metamod:Source Version"); +#ifdef OS_WIN32 +ConVar mm_pluginsfile("mm_pluginsfile", "addons\\metamod\\metaplugins.ini", FCVAR_SPONLY, "Metamod:Source Plugins File"); +ConVar mm_basedir("mm_basedir", "addons\\metamod", FCVAR_SPONLY, "Metamod:Source base folder"); +#else +ConVar mm_pluginsfile("mm_pluginsfile", "addons/metamod/metaplugins.ini", FCVAR_SPONLY, "Metamod:Source Plugins File"); +ConVar mm_basedir("mm_basedir", "addons/metamod", FCVAR_SPONLY, "Metamod:Source base folder"); +#endif + +CON_COMMAND(meta, "Metamod:Source Menu") +{ + IVEngineServer *e = g_Engine.engine; + + int args = e->Cmd_Argc(); + + if (!g_GameDll.loaded && !g_bLevelChanged) + { + CONMSG("WARNING: You must change the map to activate Metamod:Source.\n"); + return; + } + + if (args >= 2) + { + const char *command = e->Cmd_Argv(1); + if (strcmp(command, "credits") == 0) + { + CONMSG("Metamod:Source was developed by:\n"); + CONMSG(" SourceHook: Pavol \"PM OnoTo\" Marko\n"); + CONMSG(" GameDLL/Plugins: David \"BAILOPAN\" Anderson\n"); + CONMSG(" GameDLL: Scott \"DS\" Ehlert\n"); + CONMSG("For more information, see the official website\n"); + CONMSG("http://www.metamodsource.net/\n"); + + return; + } else if (strcmp(command, "version") == 0) { + CONMSG("Metamod:Source version %s\n", METAMOD_VERSION); +#if defined(MMS_GENERATED_BUILD) + CONMSG("Built from: https://github.com/alliedmodders/metamod-source/commit/%s\n", METAMOD_BUILD_SHA); +#endif + CONMSG("Build ID: %s:%s\n", METAMOD_BUILD_LOCAL_REV, METAMOD_BUILD_SHA); + if (g_GameDll.loaded) + { + CONMSG("Loaded As: GameDLL (gameinfo.txt)\n"); + } + else + { + CONMSG("Loaded As: Valve Server Plugin\n"); + } + CONMSG("Compiled on: %s\n", SOURCEMM_DATE); + CONMSG("Plugin interface version: %d:%d\n", PLAPI_VERSION, PLAPI_MIN_VERSION); + CONMSG("SourceHook version: %d:%d\n", g_SourceHook.GetIfaceVersion(), g_SourceHook.GetImplVersion()); + CONMSG("http://www.metamodsource.net/\n"); + + return; + } else if (strcmp(command, "game") == 0) { + char bin_path[PATH_SIZE]; + GetFileOfAddress((void*)g_GameDll.factory, bin_path, sizeof(bin_path)); + + CONMSG("GameDLL Information\n"); + CONMSG(" Description: %s\n", g_GameDll.pGameDLL->GetGameDescription()); + CONMSG(" Mod Path: %s\n", g_ModPath.c_str()); + CONMSG(" DLL Path: %s\n", bin_path); + CONMSG(" Interface: ServerGameDLL%03d\n", g_GameDllVersion); + + if (g_Engine.original) + { + CONMSG(" Engine: Original (pre-Episode 1)\n"); + } + else + { + CONMSG(" Engine: Episode 1 (2004)\n"); + } + + // Display user messages + const char *msgname; + int msgsize; + int msgcount = g_SmmAPI.GetUserMessageCount(); + + if (msgcount > 0) + { + CONMSG(" User Messages: %-32.31s %-5s %-5s\n", "Name", "Index", "Size"); + + for (int i = 0; i < msgcount; i++) + { + msgname = g_SmmAPI.GetUserMessage(i, &msgsize); + + CONMSG(" %-32.31s %-5d %-5d\n", msgname, i, msgsize); + } + + CONMSG(" %d user message%s in total\n", msgcount, (msgcount > 1) ? "s" : ""); + } else { + CONMSG(" User Messages: None\n"); + } + + return; + } else if (strcmp(command, "refresh") == 0) { + char filepath[PATH_SIZE], vdfpath[PATH_SIZE]; + g_SmmAPI.PathFormat(filepath, sizeof(filepath), "%s/%s", g_ModPath.c_str(), GetPluginsFile()); + g_SmmAPI.PathFormat(vdfpath, sizeof(vdfpath), "%s/%s", g_ModPath.c_str(), GetMetamodBaseDir()); + + LoadPlugins(filepath, vdfpath); + + return; + } else if (strcmp(command, "list") == 0) { + size_t len; + PluginIter i; + char buffer[255]; + ISmmPlugin *plapi; + const char *plname; + SourceMM::CPluginManager::CPlugin *pl; + unsigned int plnum = g_PluginMngr.GetPluginCount(); + +#define IS_STR_FILLED(var) (var != NULL && var[0] != '\0') + + if (!plnum) + { + CONMSG("No plugins loaded.\n"); + return; + } + else + { + CONMSG("Listing %d plugin%s:\n", plnum, (plnum > 1) ? "s" : ""); + } + + for (i=g_PluginMngr._begin(); i!=g_PluginMngr._end(); i++) + { + pl = (*i); + if (!pl) + { + break; + } + + len = 0; + + if (pl->m_Status != Pl_Running) + { + len += UTIL_Format(buffer, sizeof(buffer), " [%02d] <%s>", pl->m_Id, g_PluginMngr.GetStatusText(pl)); + } + else + { + len += UTIL_Format(buffer, sizeof(buffer), " [%02d]", pl->m_Id); + } + + if ((plapi = pl->m_API)) + { + plname = IS_STR_FILLED(plapi->GetName()) ? plapi->GetName() : pl->m_File.c_str(); + len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " %s", plname); + + if (IS_STR_FILLED(plapi->GetVersion())) + { + len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", plapi->GetVersion()); + } + if (IS_STR_FILLED(plapi->GetAuthor())) + { + UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", plapi->GetAuthor()); + } + } + + CONMSG("%s\n", buffer); + } + + return; + } else if (strcmp(command, "cmds") == 0) { + if (args >= 3) + { + int id = atoi(e->Cmd_Argv(2)); + SourceMM::CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id); + + if (!pl) + { + CONMSG("Plugin %d not found.\n", id); + return; + } + + if (!pl->m_API) + { + CONMSG("Plugin %d is not loaded.\n", id); + } else { + CONMSG("Console commands for %s:\n", pl->m_API->GetName()); + SourceHook::List::iterator ci; + size_t count = 0; + + for (ci=pl->m_Cmds.begin(); ci!=pl->m_Cmds.end(); ci++) + { + count++; + CONMSG(" [%5d] %-s\n", count, (*ci)->GetName()); + } + } + } else { + CONMSG("Usage: meta cmds \n"); + } + + return; + } else if (strcmp(command, "cvars") == 0) { + if (args >= 3) + { + int id = atoi(e->Cmd_Argv(2)); + SourceMM::CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id); + + if (!pl) + { + CONMSG("Plugin %d not found.\n", id); + return; + } + + if (!pl->m_API) + { + CONMSG("Plugin %d is not loaded.\n", id); + } else { + CONMSG("Registered cvars for %s:\n", pl->m_API->GetName()); + SourceHook::List::iterator ci; + size_t count = 0; + + for (ci=pl->m_Cvars.begin(); ci!=pl->m_Cvars.end(); ci++) + { + count++; + CONMSG(" [%5d] %-s\n", count, (*ci)->GetName()); + } + } + } else { + CONMSG("Usage: meta cvars \n"); + } + + return; + } else if (strcmp(command, "info") == 0) { + if (args >= 3) + { + int id = atoi(e->Cmd_Argv(2)); + SourceMM::CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id); + if (!pl) + { + CONMSG("Plugin %d not found.\n", id); + return; + } + + if (!pl->m_API) + { + CONMSG("Plugin %d is not loaded.\n", id); + } else { + if (pl->m_Status == Pl_Paused) + { + CONMSG("Plugin %d is paused.\n", id); + } else if (pl->m_Status == Pl_Running) { + char run_msg[255]; + bool run = false; + if (pl->m_API && pl->m_API->QueryRunning(run_msg, sizeof(run_msg)-1)) + run = true; + if (run) + { + CONMSG("Plugin %d is running.\n", id); + } else { + CONMSG("Plugin %d is stopped: %s\n", id, run_msg); + } + } + CONMSG(" Name: \"%s\" by %s\n", pl->m_API->GetName(), pl->m_API->GetAuthor()); + CONMSG(" Version: %s\n", pl->m_API->GetVersion()); + CONMSG(" Description: %s\n", pl->m_API->GetDescription()); + CONMSG(" License: %s\n", pl->m_API->GetLicense()); + CONMSG(" URL: %s\n", pl->m_API->GetURL()); + CONMSG(" Details: API %03d, Date: %s\n", pl->m_API->GetApiVersion(), pl->m_API->GetDate()); + } + CONMSG("File: %s\n\n", pl->m_File.c_str()); + + return; + } else { + CONMSG("Usage: meta info \n"); + + return; + } + } else if (strcmp(command, "pause") == 0) { + if (args >= 3) + { + int id = atoi(e->Cmd_Argv(2)); + + char error[255]; + + if (!g_PluginMngr.Pause(id, error, sizeof(error))) + { + CONMSG("Pause failed: %s\n", error); + return; + } + + CONMSG("Plugin %d has been paused.\n", id); + + return; + } else { + CONMSG("Usage: meta pause \n"); + + return; + } + } else if (strcmp(command, "unpause") == 0) { + if (args >= 3) + { + int id = atoi(e->Cmd_Argv(2)); + char error[255]; + + if (!g_PluginMngr.Unpause(id, error, sizeof(error))) + { + CONMSG("Unpause failed: %s\n", error); + return; + } + + CONMSG("Plugin %d has been unpaused.\n", id); + + return; + } else { + CONMSG("Usage: meta unpause \n"); + + return; + } + } else if (strcmp(command, "load") == 0) { + if (args >= 3) + { + const char *file = e->Cmd_Argv(2); + char full_path[255]; + + const char *alias = g_PluginMngr.LookupAlias(file); + if (alias) + { + file = alias; + } + + g_SmmAPI.GetFullPluginPath(file, full_path, sizeof(full_path)); + + char error[255]={0}; + bool already; + SourceMM::CPluginManager::CPlugin *pl; + + PluginId id = g_PluginMngr.Load(full_path, Pl_Console, already, error, sizeof(error)); + pl = g_PluginMngr.FindById(id); + if (!pl || id < Pl_MinId || (pl->m_Status < Pl_Paused)) + { + CONMSG("Failed to load plugin %s (%s).\n", file, error); + return; + } + + if (!already) + { + CONMSG("Plugin \"%s\" loaded with id %d.\n", pl->m_API->GetName(), pl->m_Id); + } else { + CONMSG("Plugin \"%s\" is already loaded as %d.\n", pl->m_API->GetName(), pl->m_Id); + } + + return; + } else { + CONMSG("Usage: meta load \n"); + + return; + } + } else if ( (strcmp(command, "alias") == 0) || + (strcmp(command, "aliases") == 0) ) { + if (args >= 4) + { + const char *alias = e->Cmd_Argv(2); + const char *value = e->Cmd_Argv(3); + + g_PluginMngr.SetAlias(alias, value); + if (value[0] == '\0') + { + CONMSG("Deleted alias: %s.\n", alias); + } else { + CONMSG("Set alias \"%s\" to: %s\n", alias, value); + } + } else if (args >= 3) { + const char *alias = e->Cmd_Argv(2); + const char *value = g_PluginMngr.LookupAlias(alias); + if (value) + { + CONMSG("Alias \"%s\" is set to: %s\n", alias, value); + } else { + CONMSG("Alias \"%s\" was not found.\n", alias); + } + } else { + SourceHook::List::iterator iter, end; + SourceMM::CNameAlias *p; + + iter = g_PluginMngr._alias_begin(); + end = g_PluginMngr._alias_end(); + size_t total = 0; + if (iter != end) + { + CONMSG("%-10.9s %s\n", "Alias", "File"); + CONMSG(" --- \n"); + for (; iter!=end; iter++) + { + p = (*iter); + CONMSG("%-10.9s %s\n", p->alias.c_str(), p->value.c_str()); + total++; + } + CONMSG(" --- \n"); + CONMSG("%d aliases total.\n", total); + } else { + CONMSG("No aliases found.\n"); + } + } + return; + } else if (strcmp(command, "unload") == 0) { + if (args >= 3) + { + const char *file = e->Cmd_Argv(2); + int id = atoi(file); + char error[255]={0}; + + if (id == 0 && isalpha(file[0])) + { + char full_path[255]; + const char *alias = g_PluginMngr.LookupAlias(file); + + if (alias) + { + file = alias; + } + + g_SmmAPI.GetFullPluginPath(file, full_path, sizeof(full_path)); + + SourceHook::List::iterator iter, end; + SourceMM::CPluginManager::CPlugin *pl; + iter = g_PluginMngr._begin(); + end = g_PluginMngr._end(); + for (; iter!=end; iter++) + { + pl = (*iter); + if (strcmp(pl->m_File.c_str(), full_path) == 0) + { + id = pl->m_Id; + break; + } + } + if (id == 0) + { + CONMSG("Plugin \"%s\" not found.\n", full_path); + return; + } + } + + if (!g_PluginMngr.Unload(id, false, error, sizeof(error))) + { + CONMSG("Unload failed: %s\n", error); + return; + } + + CONMSG("Plugin %d unloaded.\n", id); + } else { + CONMSG("Usage: meta unload \n"); + } + return; + } else if (strcmp(command, "force_unload") == 0) { + if (args >= 3) + { + int id = atoi(e->Cmd_Argv(2)); + char error[255]={0}; + + if (!g_PluginMngr.Unload(id, false, error, sizeof(error))) + { + CONMSG("Force unload failed: %s\n", error); + return; + } + + CONMSG("Plugin %d force unloaded.\n", id); + + return; + } else { + CONMSG("Usage: meta force_unload \n"); + + return; + } + } else if (strcmp(command, "clear") == 0) { + if (!g_PluginMngr.UnloadAll()) + { + CONMSG("One or more plugins resisted removal (cleaned anyway).\n"); + return; + } + + CONMSG("All plugins unloaded.\n"); + + return; + } else if (strcmp(command, "retry") == 0) { + if (args >= 3) + { + int id = atoi(e->Cmd_Argv(2)); + char error[255]; + + if (!g_PluginMngr.Retry(id, error, sizeof(error))) + { + CONMSG("Error reloading plugin: %s\n", error); + return; + } + + CONMSG("Plugin %d successfully reloaded.\n", id); + + return; + } else { + CONMSG("Usage: meta retry \n"); + + return; + } + } + } + + CONMSG("Metamod:Source Menu\n"); + CONMSG("usage: meta [arguments]\n"); + CONMSG(" alias - List or set an alias\n"); + CONMSG(" clear - Unload all plugins forcefully\n"); + CONMSG(" cmds - Show plugin commands\n"); + CONMSG(" cvars - Show plugin cvars\n"); + CONMSG(" credits - About Metamod:Source\n"); + CONMSG(" force_unload - Forcefully unload a plugin\n"); + CONMSG(" game - Information about GameDLL\n"); + CONMSG(" info - Information about a plugin\n"); + CONMSG(" list - List plugins\n"); + CONMSG(" load - Load a plugin\n"); + CONMSG(" pause - Pause a running plugin\n"); + CONMSG(" refresh - Reparse plugin files\n"); + CONMSG(" retry - Attempt to reload a plugin\n"); + CONMSG(" unload - Unload a loaded plugin\n"); + CONMSG(" unpause - Unpause a paused plugin\n"); + CONMSG(" version - Version information\n"); +} + +void ClientCommand_handler(edict_t *client) +{ + IVEngineServer *e = g_Engine.engine; + const char *cmd = e->Cmd_Argv(0); + + if (strcmp(cmd, "meta") == 0) + { + int args = e->Cmd_Argc(); + if (args == 2) + { + const char *subcmd = e->Cmd_Argv(1); + + if (strcmp(subcmd, "credits") == 0) + { + CLIENT_CONMSG(client, "Metamod:Source was developed by:\n"); + CLIENT_CONMSG(client, " SourceHook: Pavol \"PM OnoTo\" Marko\n"); + CLIENT_CONMSG(client, " Core: David \"BAILOPAN\" Anderson\n"); + CLIENT_CONMSG(client, " Core: Scott \"DS\" Ehlert\n"); + CLIENT_CONMSG(client, "For more information, see the official website\n"); + CLIENT_CONMSG(client, "http://www.metamodsource.net/\n"); + + RETURN_META(MRES_SUPERCEDE); + } else if(strcmp(subcmd, "version") == 0) { + CLIENT_CONMSG(client, "Metamod:Source version %s\n", METAMOD_VERSION); + CLIENT_CONMSG(client, "Compiled on: %s\n", SOURCEMM_DATE); + CLIENT_CONMSG(client, "Plugin interface version: %d:%d\n", PLAPI_VERSION, PLAPI_MIN_VERSION); + CLIENT_CONMSG(client, "SourceHook version: %d:%d\n", g_SourceHook.GetIfaceVersion(), g_SourceHook.GetImplVersion()); + CLIENT_CONMSG(client, "http://www.metamodsource.net/\n"); + + RETURN_META(MRES_SUPERCEDE); + } else if(strcmp(subcmd, "list") == 0) { + SourceMM::CPluginManager::CPlugin *pl; + ISmmPlugin *plapi; + const char *plname; + PluginIter i; + char buffer[256]; + int len = 0; + int plnum = 0; + + for (i = g_PluginMngr._begin(); i != g_PluginMngr._end(); i++, len=0) + { + pl = (*i); + if (pl && pl->m_Status == Pl_Running) + { + plapi = pl->m_API; + if (!plapi || !plapi->QueryRunning(NULL, 0)) + { + continue; + } + plnum++; + + len += UTIL_Format(buffer, sizeof(buffer), " [%02d]", plnum); + + plname = IS_STR_FILLED(plapi->GetName()) ? plapi->GetName() : pl->m_File.c_str(); + len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " %s", plname); + + if (IS_STR_FILLED(plapi->GetVersion())) + { + len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", plapi->GetVersion()); + } + if (IS_STR_FILLED(plapi->GetAuthor())) + { + UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", plapi->GetAuthor()); + } + + CLIENT_CONMSG(client, "%s\n", buffer); + } + } + + if (!plnum) + { + CLIENT_CONMSG(client, "No active plugins loaded.\n"); + } + + RETURN_META(MRES_SUPERCEDE); + } + } + + CLIENT_CONMSG(client, "Metamod:Source Menu\n"); + CLIENT_CONMSG(client, "usage: meta \n"); + CLIENT_CONMSG(client, " credits - About Metamod:Source\n"); + CLIENT_CONMSG(client, " list - List plugins\n"); + CLIENT_CONMSG(client, " version - Version information\n"); + + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void SMConVarAccessor::UnloadMetamodCommands() +{ + Unregister(&metamod_version); + Unregister(&mm_pluginsfile); + Unregister(&mm_basedir); + Unregister(&meta_command); +} + +const char *GetPluginsFile() +{ + return mm_pluginsfile.GetString(); +} + +const char *GetMetamodBaseDir() +{ + return mm_basedir.GetString(); +} + +/* Signature for ICvar::GetCommands() in vstdlib for Win32 and Linux. + * + * 20226EE0 A1 50 5C 5A 20 mov eax,dword ptr ds:[205A5C50h] <-- What we want + * 20226EE5 C3 ret + */ +#define CMDLIST_SIG "\xA1\x2A\x2A\x2A\x2A\xC3" +#define CMDLIST_SIGLEN 6 + +/* Linux symbol name of ConCommandBase list in vstdlib */ +#define CMDLIST_SYMBOL "_ZN14ConCommandBase18s_pConCommandBasesE" + +/* This function retrieves the address of the var that holds the top of the ConCommandBase list. + * Having this allows us to change the beginning of this list with ease. + * + * This craziness eliminates the need for the eternal command/cvar used previously which + * could have caused a crash as a result of registering commands/cvars more than once. + */ +bool SMConVarAccessor::InitConCommandBaseList() +{ + char *vfunc = UTIL_GetOrigFunction(&ICvar::GetCommands, g_Engine.icvar); + + if (!vfunc) + { + return false; + } + +#ifdef OS_WIN32 + if (UTIL_VerifySignature(vfunc, CMDLIST_SIG, CMDLIST_SIGLEN)) + { + /* Skip past 0xA1 and get addr of ConCommandBase list var */ + m_TopConCommandBase = *reinterpret_cast(vfunc + 1); + return true; + } +#elif defined OS_LINUX + /* Try dlsym first */ + char path[PATH_SIZE]; + if (GetFileOfAddress((void *)g_Engine.icvar, path, sizeof(path))) + { + void *handle = dlopen(path, RTLD_NOW); + if (handle) + { + m_TopConCommandBase = reinterpret_cast(dlsym(handle, CMDLIST_SYMBOL)); + dlclose(handle); + return true; + } + } + + /* If dlsym failed, then verify signature of function */ + if (!m_TopConCommandBase && UTIL_VerifySignature(vfunc, CMDLIST_SIG, CMDLIST_SIGLEN)) + { + /* Skip past 0xA1 and get addr of ConCommandBase list var */ + m_TopConCommandBase = *reinterpret_cast(vfunc + 1); + return true; + } +#endif + + return false; +} diff --git a/utils/mmsource/core-legacy/concommands.h b/utils/mmsource/core-legacy/concommands.h new file mode 100644 index 00000000..0ecf594e --- /dev/null +++ b/utils/mmsource/core-legacy/concommands.h @@ -0,0 +1,44 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2008 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * ============================ + */ + +#ifndef _INCLUDE_CONCOMMANDS_H +#define _INCLUDE_CONCOMMANDS_H + +/** + * @brief Header for console commands + * @file concommands.h + */ + +#include "convar_smm.h" +#include "sourcemm.h" +#include "sh_list.h" + +class SMConVarAccessor : public IConCommandBaseAccessor +{ + SourceHook::List m_RegisteredCommands; + ConCommandBase **m_TopConCommandBase; +public: + SMConVarAccessor(); + virtual bool RegisterConCommandBase(ConCommandBase *pCommand); + bool Register(ConCommandBase *pCommand); + void MarkCommandsAsGameDLL(); + bool InitConCommandBaseList(); + void Unregister(ConCommandBase *pCommand); + void UnloadMetamodCommands(); +}; + +void ClientCommand_handler(edict_t *client); + +const char *GetPluginsFile(); +const char *GetMetamodBaseDir(); + +extern SMConVarAccessor g_SMConVarAccessor; + +#endif //_INCLUDE_CONCOMMANDS_H diff --git a/utils/mmsource/core-legacy/convar_smm.h b/utils/mmsource/core-legacy/convar_smm.h new file mode 100644 index 00000000..dd4d9e33 --- /dev/null +++ b/utils/mmsource/core-legacy/convar_smm.h @@ -0,0 +1,528 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date$ +// +//----------------------------------------------------------------------------- +// $NoKeywords: $ +//=============================================================================// + +#ifndef CONVAR_H +#define CONVAR_H +#if _WIN32 +#pragma once +#endif + +#include "tier0/dbg.h" + +#ifdef _WIN32 +#define FORCEINLINE_CVAR FORCEINLINE +#elif _LINUX +#define FORCEINLINE_CVAR __inline__ FORCEINLINE +#else +#error "implement me" +#endif + +// The default, no flags at all +#define FCVAR_NONE 0 + +// Command to ConVars and ConCommands +// ConVar Systems +#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc. +#define FCVAR_LAUNCHER (1<<1) // defined by launcher +#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL +#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL +#define FCVAR_MATERIAL_SYSTEM (1<<4) // Defined by the material system. +#define FCVAR_DATACACHE (1<<19) // Defined by the datacache system. +#define FCVAR_STUDIORENDER (1<<15) // Defined by the studiorender system. +#define FCVAR_FILESYSTEM (1<<21) // Defined by the file system. +#define FCVAR_PLUGIN (1<<18) // Defined by a 3rd party plugin. +#define FCVAR_TOOLSYSTEM (1<<20) // Defined by an IToolSystem library +#define FCVAR_SOUNDSYSTEM (1<<23) // Defined by the soundsystem library +#define FCVAR_INPUTSYSTEM (1<<25) // Defined by the inputsystem dll +#define FCVAR_NETWORKSYSTEM (1<<26) // Defined by the network system +// NOTE!! if you add a cvar system, add it here too!!!! +// the engine lacks a cvar flag, but needs it for xbox +// an engine cvar is thus a cvar not marked with any other system +#define FCVAR_NON_ENGINE ((FCVAR_LAUNCHER|FCVAR_GAMEDLL|FCVAR_CLIENTDLL|FCVAR_MATERIAL_SYSTEM|FCVAR_DATACACHE|FCVAR_STUDIORENDER|FCVAR_FILESYSTEM|FCVAR_PLUGIN|FCVAR_TOOLSYSTEM|FCVAR_SOUNDSYSTEM|FCVAR_INPUTSYSTEM|FCVAR_NETWORKSYSTEM)) + +// ConVar only +#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value +#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server. +#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc +#define FCVAR_NOTIFY (1<<8) // notifies players when changed +#define FCVAR_USERINFO (1<<9) // changes the client's info string +#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats + +#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ). +#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log +#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar + +// It's a ConVar that's shared between the client and the server. +// At signon, the values of all such ConVars are sent from the server to the client (skipped for local +// client, of course ) +// If a change is requested it must come from the console (i.e., no remote client changes) +// If a value is changed while a server is active, it's replicated to all connected clients +#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time +#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file +#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles + +#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server + +#define FCVAR_ARCHIVE_XBOX (1<<24) // cvar written to config.cfg on the Xbox + + +// #define FCVAR_AVAILABLE (1<<27) +// #define FCVAR_AVAILABLE (1<<28) +// #define FCVAR_AVAILABLE (1<<29) +// #define FCVAR_AVAILABLE (1<<30) +// #define FCVAR_AVAILABLE (1<<31) + + +class ConVar; +class ConCommand; +class ConCommandBase; + +// Any executable that wants to use ConVars need to implement one of +// these to hook up access to console variables. +class IConCommandBaseAccessor +{ +public: + // Flags is a combination of FCVAR flags in cvar.h. + // hOut is filled in with a handle to the variable. + virtual bool RegisterConCommandBase( ConCommandBase *pVar )=0; +}; + + +// You don't have to instantiate one of these, just call its +// OneTimeInit function when your executable is initializing. +class ConCommandBaseMgr +{ +public: + // Call this ONCE when the executable starts up. + static void OneTimeInit( IConCommandBaseAccessor *pAccessor ); +#ifdef _XBOX + static bool Fixup( ConCommandBase* pConCommandBase ); +#ifndef _RETAIL + static void PublishCommands( bool bForce ); +#endif +#endif +}; + +// Called when a ConVar changes value +typedef void ( *FnChangeCallback )( ConVar *var, char const *pOldString ); + +// Called when a ConCommand needs to execute +typedef void ( *FnCommandCallback )( void ); + +#define COMMAND_COMPLETION_MAXITEMS 64 +#define COMMAND_COMPLETION_ITEM_LENGTH 64 + +// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings +typedef int ( *FnCommandCompletionCallback )( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ); + +//----------------------------------------------------------------------------- +// Purpose: The base console invoked command/cvar interface +//----------------------------------------------------------------------------- +class ConCommandBase +{ + friend class ConCommandBaseMgr; + friend class CCvar; + friend class ConVar; + friend class ConCommand; + +public: + ConCommandBase( void ); + ConCommandBase( char const *pName, char const *pHelpString = 0, + int flags = 0 ); + + virtual ~ConCommandBase( void ); + + virtual bool IsCommand( void ) const; + + // Check flag + virtual bool IsBitSet( int flag ) const; + // Set flag + virtual void AddFlags( int flags ); + + // Return name of cvar + virtual char const *GetName( void ) const; + + // Return help text for cvar + virtual char const *GetHelpText( void ) const; + + // Deal with next pointer + const ConCommandBase *GetNext( void ) const; + void SetNext( ConCommandBase *next ); + + virtual bool IsRegistered( void ) const; + + // Global methods + static ConCommandBase const *GetCommands( void ); + static void AddToList( ConCommandBase *var ); + static void RemoveFlaggedCommands( int flag ); + static void RevertFlaggedCvars( int flag ); + static ConCommandBase const *FindCommand( char const *name ); + +protected: + virtual void Create( char const *pName, char const *pHelpString = 0, + int flags = 0 ); + + // Used internally by OneTimeInit to initialize. + virtual void Init(); + + // Internal copy routine ( uses new operator from correct module ) + char *CopyString( char const *from ); + + // Next ConVar in chain + ConCommandBase *m_pNext; + +private: + // Has the cvar been added to the global list? + bool m_bRegistered; + + // Static data + char const *m_pszName; + char const *m_pszHelpString; + + // ConVar flags + int m_nFlags; + +protected: + + // ConVars add themselves to this list for the executable. Then ConVarMgr::Init() runs through + // all the console variables and registers them. + static ConCommandBase *s_pConCommandBases; + + // ConVars in this executable use this 'global' to access values. + static IConCommandBaseAccessor *s_pAccessor; +public: + inline void SetRegistered(bool registered) + { + m_bRegistered = registered; + } +}; + +//----------------------------------------------------------------------------- +// Purpose: The console invoked command +//----------------------------------------------------------------------------- +class ConCommand : public ConCommandBase +{ +friend class ConCommandBaseMgr; +friend class CCvar; +#ifdef _STATIC_LINKED +friend class G_ConCommand; +friend class C_ConCommand; +friend class M_ConCommand; +friend class S_ConCommand; +friend class D_ConCommand; +#endif + +public: + typedef ConCommandBase BaseClass; + + ConCommand( void ); + ConCommand( char const *pName, FnCommandCallback callback, + char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ); + + virtual ~ConCommand( void ); + + virtual bool IsCommand( void ) const; + + virtual int AutoCompleteSuggest( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ); + + virtual bool CanAutoComplete( void ); + + // Invoke the function + virtual void Dispatch( void ); +private: + virtual void Create( char const *pName, FnCommandCallback callback, + char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ); + + // Call this function when executing the command + FnCommandCallback m_fnCommandCallback; + + FnCommandCompletionCallback m_fnCompletionCallback; + bool m_bHasCompletionCallback; +public: + inline FnCommandCallback GetCallback() { return m_fnCommandCallback; } +}; + +//----------------------------------------------------------------------------- +// Purpose: A console variable +//----------------------------------------------------------------------------- +class ConVar : public ConCommandBase +{ +friend class ConCommandBaseMgr; +friend class CCvar; +friend class CDefaultCvar; +#ifdef _STATIC_LINKED +friend class G_ConVar; +friend class C_ConVar; +friend class M_ConVar; +friend class S_ConVar; +friend class D_ConVar; +#endif + +public: + typedef ConCommandBase BaseClass; + + ConVar( char const *pName, char const *pDefaultValue, int flags = 0); + + ConVar( char const *pName, char const *pDefaultValue, int flags, + char const *pHelpString ); + ConVar( char const *pName, char const *pDefaultValue, int flags, + char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ); + ConVar( char const *pName, char const *pDefaultValue, int flags, + char const *pHelpString, FnChangeCallback callback ); + ConVar( char const *pName, char const *pDefaultValue, int flags, + char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, + FnChangeCallback callback ); + + virtual ~ConVar( void ); + + virtual bool IsBitSet( int flag ) const; + virtual char const* GetHelpText( void ) const; + virtual bool IsRegistered( void ) const; + virtual char const *GetName( void ) const; + virtual void AddFlags( int flags ); + virtual bool IsCommand( void ) const; + + // Install a change callback (there shouldn't already be one....) + void InstallChangeCallback( FnChangeCallback callback ); + + // Retrieve value + FORCEINLINE_CVAR float GetFloat( void ) const; + FORCEINLINE_CVAR int GetInt( void ) const; + FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); } + FORCEINLINE_CVAR char const *GetString( void ) const; + + // Any function that allocates/frees memory needs to be virtual or else you'll have crashes + // from alloc/free across dll/exe boundaries. + + // These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue). + virtual void SetValue( char const *value ); + virtual void SetValue( float value ); + virtual void SetValue( int value ); + + // Reset to default value + void Revert( void ); + + // True if it has a min/max setting + bool GetMin( float& minVal ) const; + bool GetMax( float& maxVal ) const; + char const *GetDefault( void ) const; + + static void RevertAll( void ); +private: + // Called by CCvar when the value of a var is changing. + virtual void InternalSetValue(char const *value); + // For CVARs marked FCVAR_NEVER_AS_STRING + virtual void InternalSetFloatValue( float fNewValue ); + virtual void InternalSetIntValue( int nValue ); + + virtual bool ClampValue( float& value ); + virtual void ChangeStringValue( char const *tempVal ); + + virtual void Create( char const *pName, char const *pDefaultValue, int flags = 0, + char const *pHelpString = 0, bool bMin = false, float fMin = 0.0, + bool bMax = false, float fMax = false, FnChangeCallback callback = 0 ); + + // Used internally by OneTimeInit to initialize. + virtual void Init(); + +private: + + // This either points to "this" or it points to the original declaration of a ConVar. + // This allows ConVars to exist in separate modules, and they all use the first one to be declared. + // m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar). + ConVar *m_pParent; + + // Static data + char const *m_pszDefaultValue; + + // Value + // Dynamically allocated + char *m_pszString; + int m_StringLength; + + // Values + float m_fValue; + int m_nValue; + + // Min/Max values + bool m_bHasMin; + float m_fMinVal; + bool m_bHasMax; + float m_fMaxVal; + + // Call this function when ConVar changes + FnChangeCallback m_fnChangeCallback; +}; + + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as a float +// Output : float +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR float ConVar::GetFloat( void ) const +{ + return m_pParent->m_fValue; +} + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as an int +// Output : int +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR int ConVar::GetInt( void ) const +{ + return m_pParent->m_nValue; +} + + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc. +// Output : char const * +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR char const *ConVar::GetString( void ) const +{ + if ( m_nFlags & FCVAR_NEVER_AS_STRING ) + { + return "FCVAR_NEVER_AS_STRING"; + } + + return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : ""; +} + + +#ifdef _STATIC_LINKED +// identifies subsystem via piggybacking constructors with flags +class G_ConCommand : public ConCommand +{ +public: + G_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_GAMEDLL, completionFunc) {} +}; + +class C_ConCommand : public ConCommand +{ +public: + C_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_CLIENTDLL, completionFunc) {} +}; + +class M_ConCommand : public ConCommand +{ +public: + M_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_MATERIAL_SYSTEM, completionFunc) {} +}; + +class S_ConCommand : public ConCommand +{ +public: + S_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_STUDIORENDER, completionFunc) {} +}; + +class D_ConCommand : public ConCommand +{ +public: + D_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_DATACACHE, completionFunc) {} +}; + +typedef void ( *G_FnChangeCallback )( G_ConVar *var, char const *pOldString ); +typedef void ( *C_FnChangeCallback )( C_ConVar *var, char const *pOldString ); +typedef void ( *M_FnChangeCallback )( M_ConVar *var, char const *pOldString ); +typedef void ( *S_FnChangeCallback )( S_ConVar *var, char const *pOldString ); +typedef void ( *D_FnChangeCallback )( D_ConVar *var, char const *pOldString ); + +class G_ConVar : public ConVar +{ +public: + G_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL) {} + G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString ) {} + G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax) {} + G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, (FnChangeCallback)callback ) {} + G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {} +}; + +class C_ConVar : public ConVar +{ +public: + C_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL) {} + C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString ) {} + C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax) {} + C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, (FnChangeCallback)callback ) {} + C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {} +}; + +class M_ConVar : public ConVar +{ +public: + M_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM) {} + M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString ) {} + M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax) {} + M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, (FnChangeCallback)callback ) {} + M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {} +}; + +class S_ConVar : public ConVar +{ +public: + S_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER) {} + S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString ) {} + S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax) {} + S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, (FnChangeCallback)callback ) {} + S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, S_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {} +}; + +class D_ConVar : public ConVar +{ +public: + D_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE) {} + D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString ) {} + D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax) {} + D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, (FnChangeCallback)callback ) {} + D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, D_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {} +}; + +// redirect these declarations to their specific subsystem +#ifdef GAME_DLL +#define ConCommand G_ConCommand +#define ConVar G_ConVar +#endif +#ifdef CLIENT_DLL +#define ConCommand C_ConCommand +#define ConVar C_ConVar +#endif +#ifdef MATERIALSYSTEM_DLL +#define ConCommand M_ConCommand +#define ConVar M_ConVar +#endif +#ifdef STUDIORENDER_DLL +#define ConCommand S_ConCommand +#define ConVar S_ConVar +#endif +#ifdef DATACACHE_DLL +#define ConCommand D_ConCommand +#define ConVar D_ConVar +#endif +#endif // _STATIC_LINKED + +//----------------------------------------------------------------------------- +// Purpose: Utility to quicky generate a simple console command +//----------------------------------------------------------------------------- +#define CON_COMMAND( name, description ) \ + static void name(); \ + static ConCommand name##_command( #name, name, description ); \ + static void name() + +//----------------------------------------------------------------------------- +// Purpose: Utility to quicky generate a simple console command +//----------------------------------------------------------------------------- +#define CON_COMMAND_F( name, description, flags ) \ + static void name(); \ + static ConCommand name##_command( #name, name, description, flags ); \ + static void name() + + +#endif // CONVAR_H diff --git a/utils/mmsource/core-legacy/gamedll_bridge.cpp b/utils/mmsource/core-legacy/gamedll_bridge.cpp new file mode 100644 index 00000000..bcbc5099 --- /dev/null +++ b/utils/mmsource/core-legacy/gamedll_bridge.cpp @@ -0,0 +1,133 @@ +/** + * vim: set ts=4 : + * ====================================================== + * Metamod:Source + * Copyright (C) 2004-2008 AlliedModders LLC and authors. + * All rights reserved. + * ====================================================== + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in a + * product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * Version: $Id$ + */ + +#include +#include "sourcemm.h" +#include "CPlugin.h" +#include + +using namespace SourceMM; + +#define IFACE_MACRO(orig,nam) \ + CPluginManager::CPlugin *pl; \ + SourceHook::List::iterator event; \ + IMetamodListener *api; \ + int mret = 0; \ + void *val = NULL; \ + for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \ + pl = (*iter); \ + for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \ + api = (*event).event; \ + mret = IFACE_FAILED; \ + if ( (val=api->On##nam##Query(iface, &mret)) != NULL ) { \ + if (ret) *ret = mret; \ + return val; \ + } \ + } \ + } \ + return (orig)(iface, ret); + + +class GameDllBridge : public IGameDllBridge +{ +public: + virtual bool DLLInit_Pre(const gamedll_bridge_info *info, char *buffer, size_t maxlength) + { + assert(!g_GameDll.loaded && !g_bIsBridgedAsVsp); + LoadAsGameDLL(info); + return true; + } + virtual void DLLInit_Post(int *isgdUnload) + { + SourceHook::MemFuncInfo mfi; + + mfi.isVirtual = false; + SourceHook::GetFuncInfo(&IServerGameDLL::DLLShutdown, mfi); + assert(mfi.isVirtual); + assert(mfi.vtbloffs == 0); + assert(mfi.thisptroffs == 0); + *isgdUnload = mfi.vtblindex; + + g_PluginMngr.SetAllLoaded(); + } + virtual void *QueryInterface(const char *iface, int *ret) + { + /* We use this interface for responding to the meta client command */ + if (strncmp(iface, "ServerGameClients", 17) == 0) + { + void *ptr = (g_GameDll.factory)(iface, ret); + g_GameDll.pGameClients = static_cast(ptr); + return ptr; + } + + /* If we got here, there's definitely a GameDLL */ + IFACE_MACRO(g_GameDll.factory, GameDLL); + } + virtual void Unload() + { + UnloadMetamod(true); + } +}; + +GameDllBridge mm14_gamedll_bridge; + +SMM_API IGameDllBridge * +GetGameDllBridge() +{ + return &mm14_gamedll_bridge; +} + +void *ServerFactory(const char *name, int *code) +{ + return mm14_gamedll_bridge.QueryInterface(name, code); +} + +/* Wrapper function. This is called when the GameDLL thinks it's using + * the engine's real engineFactory. + */ +void *EngineFactory(const char *iface, int *ret) +{ + IFACE_MACRO(g_Engine.engineFactory, Engine); +} + +/* Wrapper function. This is called when the GameDLL thinks it's using + * the engine's real physicsFactory. + */ +void *PhysicsFactory(const char *iface, int *ret) +{ + IFACE_MACRO(g_Engine.physicsFactory, Physics); +} + +/* Wrapper function. This is called when the GameDLL thinks it's using + * the engine's real fileSystemFactory. + */ +void *FileSystemFactory(const char *iface, int *ret) +{ + IFACE_MACRO(g_Engine.fileSystemFactory, FileSystem); +} + + diff --git a/utils/mmsource/core-legacy/msvc10/mm_core-legacy.sln b/utils/mmsource/core-legacy/msvc10/mm_core-legacy.sln new file mode 100644 index 00000000..981189c3 --- /dev/null +++ b/utils/mmsource/core-legacy/msvc10/mm_core-legacy.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mm_core-legacy", "mm_core-legacy.vcxproj", "{F7D47743-73B3-49B5-9D76-2333C5DFD565}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug|Win32.ActiveCfg = Debug|Win32 + {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug|Win32.Build.0 = Debug|Win32 + {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release|Win32.ActiveCfg = Release|Win32 + {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/utils/mmsource/core-legacy/msvc10/mm_core-legacy.vcxproj b/utils/mmsource/core-legacy/msvc10/mm_core-legacy.vcxproj new file mode 100644 index 00000000..f8766459 --- /dev/null +++ b/utils/mmsource/core-legacy/msvc10/mm_core-legacy.vcxproj @@ -0,0 +1,170 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {03B77DF1-F59B-4A86-AD80-8A60BDA3F491} + mm_core-legacy + Win32Proj + + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(Configuration)\ + $(Configuration)\ + true + $(Configuration)\ + $(Configuration)\ + false + + + metamod.1.ep1 + + + metamod.1.ep1 + + + + Disabled + ..;..\..\loader;..\..\public;..\sourcehook;$(HL2SDK)\public;$(HL2SDK)\public\dlls;$(HL2SDK)\public\engine;$(HL2SDK)\public\tier0;$(HL2SDK)\public\tier1;$(HL2SDK)\public\vstdlib;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + false + + + Level3 + EditAndContinue + + + BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) + ..\..\public;%(AdditionalIncludeDirectories) + + + $(HL2SDK)\lib\public\tier0.lib;$(HL2SDK)\lib\public\tier1.lib;$(HL2SDK)\lib\public\vstdlib.lib;%(AdditionalDependencies) + $(OutDir)$(TargetFileName) + libc.lib;libcd.lib;libcmt.lib;%(IgnoreSpecificDefaultLibraries) + true + $(OutDir)sourcemm.pdb + Windows + false + false + + + $(OutDir)sourcemm.lib + MachineX86 + + + IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" + + + + + Full + Speed + true + ..;..\..\loader;..\..\public;..\sourcehook;$(HL2SDK)\public;$(HL2SDK)\public\dlls;$(HL2SDK)\public\engine;$(HL2SDK)\public\tier0;$(HL2SDK)\public\tier1;$(HL2SDK)\public\vstdlib;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + Sync + MultiThreaded + false + false + + + Level3 + ProgramDatabase + + + BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) + ..\..\public;%(AdditionalIncludeDirectories) + + + $(HL2SDK)\lib\public\tier0.lib;$(HL2SDK)\lib\public\tier1.lib;$(HL2SDK)\lib\public\vstdlib.lib;%(AdditionalDependencies) + $(OutDir)$(TargetFileName) + libc.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) + true + Windows + true + true + false + + + $(OutDir)sourcemm.lib + MachineX86 + + + IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/utils/mmsource/core-legacy/msvc10/mm_core-legacy.vcxproj.filters b/utils/mmsource/core-legacy/msvc10/mm_core-legacy.vcxproj.filters new file mode 100644 index 00000000..6b7d6ef0 --- /dev/null +++ b/utils/mmsource/core-legacy/msvc10/mm_core-legacy.vcxproj.filters @@ -0,0 +1,133 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + {e1f942fd-e188-4408-a347-29a0bd790807} + + + {6c8edd0d-fc24-4c2a-8eb6-567adec28d62} + + + {4fe57361-d4c2-4541-b142-589bf1c4bad5} + + + {e9b1d0a7-f08b-4b0a-9d69-d88f827f5ad3} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + SourceHook\Headers + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Interfaces + + + Interfaces + + + Interfaces + + + SourceHook + + + SourceHook + + + SourceHook + + + SourceHook + + + SourceHook + + + SourceHook\Headers + + + SourceHook\Headers + + + SourceHook\Headers + + + SourceHook\Headers + + + SourceHook\Headers + + + HL2SDK + + + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/utils/mmsource/core-legacy/msvc9/mm_core-legacy.sln b/utils/mmsource/core-legacy/msvc9/mm_core-legacy.sln new file mode 100644 index 00000000..4e0f35a6 --- /dev/null +++ b/utils/mmsource/core-legacy/msvc9/mm_core-legacy.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mm_core-legacy", "mm_core-legacy.vcproj", "{F7D47743-73B3-49B5-9D76-2333C5DFD565}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug|Win32.ActiveCfg = Debug|Win32 + {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug|Win32.Build.0 = Debug|Win32 + {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release|Win32.ActiveCfg = Release|Win32 + {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/utils/mmsource/core-legacy/msvc9/mm_core-legacy.vcproj b/utils/mmsource/core-legacy/msvc9/mm_core-legacy.vcproj new file mode 100644 index 00000000..39eedff4 --- /dev/null +++ b/utils/mmsource/core-legacy/msvc9/mm_core-legacy.vcproj @@ -0,0 +1,357 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/utils/mmsource/core-legacy/oslink.cpp b/utils/mmsource/core-legacy/oslink.cpp new file mode 100644 index 00000000..9f0a28b4 --- /dev/null +++ b/utils/mmsource/core-legacy/oslink.cpp @@ -0,0 +1,81 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2008 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * ============================ + */ + +/** + * @brief Implements OS-dependant functions from oslink.h + * @file oslink.cpp + */ + +#include +#include "oslink.h" +#ifdef __linux +#include +#endif + +#if defined __WIN32__ || defined _WIN32 || defined WIN32 +const char *dlerror() +{ + static char buf[1024]; + DWORD num; + + num = GetLastError(); + + if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + num, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + buf, + sizeof(buf), + NULL) + == 0) + { + _snprintf(buf, sizeof(buf), "unknown error %x", num); + } + + return buf; +} +#endif + +#if defined __linux__ +int GetLastError() +{ + return errno; +} + +extern "C" void __cxa_guard_acquire(void) +{ +} + +extern "C" void __cxa_guard_release(void) +{ +} +#endif + +bool GetFileOfAddress(void *pAddr, char *buffer, size_t maxlength) +{ +#if defined WIN32 || defined _WIN32 + MEMORY_BASIC_INFORMATION mem; + if (!VirtualQuery(pAddr, &mem, sizeof(mem))) + return false; + if (mem.AllocationBase == NULL) + return false; + HMODULE dll = (HMODULE)mem.AllocationBase; + GetModuleFileName(dll, (LPTSTR)buffer, maxlength); +#elif defined __linux__ + Dl_info info; + if (!dladdr(pAddr, &info)) + return false; + if (!info.dli_fbase || !info.dli_fname) + return false; + const char *dllpath = info.dli_fname; + snprintf(buffer, maxlength, "%s", dllpath); +#endif + return true; +} diff --git a/utils/mmsource/core-legacy/oslink.h b/utils/mmsource/core-legacy/oslink.h new file mode 100644 index 00000000..a9673f52 --- /dev/null +++ b/utils/mmsource/core-legacy/oslink.h @@ -0,0 +1,93 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2010 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * ============================ + */ + +#ifndef _INCLUDE_OSLINK_H +#define _INCLUDE_OSLINK_H + +/** + * @brief Defines OS-independent information + * @file oslink.h + */ + +#if defined __WIN32__ || defined _WIN32 || defined WIN32 + #define WIN32_LEAN_AND_MEAN + #define OS_WIN32 + #if defined _MSC_VER && _MSC_VER >= 1400 + #undef ARRAYSIZE + #else + #define mkdir(a) _mkdir(a) + #endif + #include + #include + #include + #define dlmount(x) LoadLibrary(x) + #define dlsym(x, s) GetProcAddress(x, s) + #define dlclose(x) FreeLibrary(x) + const char* dlerror(); + #define abspath(x, s) _fullpath(x, s, sizeof(x)) + #define PATH_SEP_STR "\\" + #define PATH_SEP_CHAR '\\' + #define ALT_SEP_CHAR '/' + #define PATH_SIZE MAX_PATH +#elif defined __linux__ + #define OS_LINUX + #include + #include + #include + #include + typedef void* HINSTANCE; + #define dlmount(x) dlopen(x,RTLD_NOW) + #define abspath(x, s) realpath(s, x) + #define PATH_SEP_STR "/" + #define PATH_SEP_CHAR '/' + #define ALT_SEP_CHAR '\\' + #define PATH_SIZE PATH_MAX + #define stricmp strcasecmp + #define strnicmp strncasecmp +#endif + +#if defined __linux__ + #include + int GetLastError(); +#endif + +bool GetFileOfAddress(void *pAddr, char *buffer, size_t maxlength); + +#if defined __WIN32__ || defined _WIN32 || defined WIN32 + #define SMM_API extern "C" __declspec(dllexport) +#elif defined __GNUC__ + #if (__GNUC__ == 4) + #define SMM_API extern "C" __attribute__ ((visibility("default"))) + #else + #define SMM_API extern "C" + #endif +#endif + +#if defined __WIN32__ || defined _WIN32 || defined WIN32 + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + typedef __int32 int32_t; + typedef unsigned __int32 uint32_t; +#elif defined __GNUC__ +#include +#if !__GLIBC_HAVE_LONG_LONG + typedef long long int64_t; + typedef unsigned long long uint64_t; +#endif +#endif + +#ifndef __linux__ + #define snprintf _snprintf + #if defined _MSC_VER && _MSC_VER < 1500 + #define vsnprintf _vsnprintf + #endif +#endif + +#endif //_INCLUDE_OSLINK_H diff --git a/utils/mmsource/core-legacy/sourcehook/FastDelegate.h b/utils/mmsource/core-legacy/sourcehook/FastDelegate.h new file mode 100644 index 00000000..a17bb1a3 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/FastDelegate.h @@ -0,0 +1,3811 @@ +// FastDelegate.h +// Efficient delegates in C++ that generate only two lines of asm code! +// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp +// +// - Don Clugston, Mar 2004. +// Major contributions were made by Jody Hagins. +// History: +// 24-Apr-04 1.0 * Submitted to CodeProject. +// 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack. +// * Improved syntax for horrible_cast (thanks Paul Bludov). +// * Tested on Metrowerks MWCC and Intel ICL (IA32) +// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL. +// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5 +// * Now works on /clr "managed C++" code on VC7, VC7.1 +// * Comeau C++ now compiles without warnings. +// * Prevent the virtual inheritance case from being used on +// VC6 and earlier, which generate incorrect code. +// * Improved warning and error messages. Non-standard hacks +// now have compile-time checks to make them safer. +// * implicit_cast used instead of static_cast in many cases. +// * If calling a const member function, a const class pointer can be used. +// * MakeDelegate() global helper function added to simplify pass-by-value. +// * Added fastdelegate.clear() +// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates) +// 30-Oct-04 1.3 * Support for (non-void) return values. +// * No more workarounds in client code! +// MSVC and Intel now use a clever hack invented by John Dlugosz: +// - The FASTDELEGATEDECLARE workaround is no longer necessary. +// - No more warning messages for VC6 +// * Less use of macros. Error messages should be more comprehensible. +// * Added include guards +// * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks). +// * Now tested on VS 2005 Express Beta, PGI C++ +// 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates. +// * <,>,<=,>= comparison operators to allow storage in ordered containers. +// * Substantial reduction of code size, especially the 'Closure' class. +// * Standardised all the compiler-specific workarounds. +// * MFP conversion now works for CodePlay (but not yet supported in the full code). +// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1 +// * New syntax: FastDelegate< int (char *, double) >. +// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric). +// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium. +// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())" +// * Fully supported by CodePlay VectorC +// * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC! +// * More optimal assignment,== and != operators for static function pointers. + +#ifndef FASTDELEGATE_H +#define FASTDELEGATE_H + +#ifdef _MSC_VER +# if _MSC_VER > 1000 +# pragma once +# endif // _MSC_VER > 1000 +#endif // #ifdef _MSC_VER + +#include // to allow <,> comparisons + +//////////////////////////////////////////////////////////////////////////////// +// Configuration options +// +//////////////////////////////////////////////////////////////////////////////// + +// Uncomment the following #define for optimally-sized delegates. +// In this case, the generated asm code is almost identical to the code you'd get +// if the compiler had native support for delegates. +// It will not work on systems where sizeof(dataptr) < sizeof(codeptr). +// Thus, it will not work for DOS compilers using the medium model. +// It will also probably fail on some DSP systems. +#define FASTDELEGATE_USESTATICFUNCTIONHACK + +// Uncomment the next line to allow function declarator syntax. +// It is automatically enabled for those compilers where it is known to work. +//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Compiler identification for workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Compiler identification. It's not easy to identify Visual C++ because +// many vendors fraudulently define Microsoft's identifiers. +#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__) +#define FASTDLGT_ISMSVC + +#if (_MSC_VER <1300) // Many workarounds are required for VC6. +#define FASTDLGT_VC6 +#pragma warning(disable:4786) // disable this ridiculous warning +#endif + +#endif + +// Does the compiler uses Microsoft's member function pointer structure? +// If so, it needs special treatment. +// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's +// identifier, _MSC_VER. We need to filter Metrowerks out. +#if defined(_MSC_VER) && !defined(__MWERKS__) +#define FASTDLGT_MICROSOFT_MFP + +#if !defined(__VECTOR_C) +// CodePlay doesn't have the __single/multi/virtual_inheritance keywords +#define FASTDLGT_HASINHERITANCE_KEYWORDS +#endif +#endif + +// Does it allow function declarator syntax? The following compilers are known to work: +#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1 +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use. +#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too. +#if defined (__MWERKS__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +#ifdef __GNUC__ // Workaround GCC bug #8271 + // At present, GCC doesn't recognize constness of MFPs in templates +#define FASTDELEGATE_GCC_BUG_8271 +#endif + + + +//////////////////////////////////////////////////////////////////////////////// +// General tricks used in this code +// +// (a) Error messages are generated by typdefing an array of negative size to +// generate compile-time errors. +// (b) Warning messages on MSVC are generated by declaring unused variables, and +// enabling the "variable XXX is never used" warning. +// (c) Unions are used in a few compiler-specific cases to perform illegal casts. +// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to +// (char *) first to ensure that the correct number of *bytes* are added. +// +//////////////////////////////////////////////////////////////////////////////// +// Helper templates +// +//////////////////////////////////////////////////////////////////////////////// + + +namespace fastdelegate { +namespace detail { // we'll hide the implementation details in a nested namespace. + +// implicit_cast< > +// I believe this was originally going to be in the C++ standard but +// was left out by accident. It's even milder than static_cast. +// I use it instead of static_cast<> to emphasize that I'm not doing +// anything nasty. +// Usage is identical to static_cast<> +template +inline OutputClass implicit_cast(InputClass input){ + return input; +} + +// horrible_cast< > +// This is truly evil. It completely subverts C++'s type system, allowing you +// to cast from any class to any other class. Technically, using a union +// to perform the cast is undefined behaviour (even in C). But we can see if +// it is OK by checking that the union is the same size as each of its members. +// horrible_cast<> should only be used for compiler-specific workarounds. +// Usage is identical to reinterpret_cast<>. + +// This union is declared outside the horrible_cast because BCC 5.5.1 +// can't inline a function with a nested class, and gives a warning. +template +union horrible_union{ + OutputClass out; + InputClass in; +}; + +template +inline OutputClass horrible_cast(const InputClass input){ + horrible_union u; + // Cause a compile-time error if in, out and u are not the same size. + // If the compile fails here, it means the compiler has peculiar + // unions which would prevent the cast from working. + typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) + && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1]; + u.in = input; + return u.out; +} + +//////////////////////////////////////////////////////////////////////////////// +// Workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Backwards compatibility: This macro used to be necessary in the virtual inheritance +// case for Intel and Microsoft. Now it just forward-declares the class. +#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME; + +// Prevent use of the static function hack with the DOS medium model. +#ifdef __MEDIUM__ +#undef FASTDELEGATE_USESTATICFUNCTIONHACK +#endif + +// DefaultVoid - a workaround for 'void' templates in VC6. +// +// (1) VC6 and earlier do not allow 'void' as a default template argument. +// (2) They also doesn't allow you to return 'void' from a function. +// +// Workaround for (1): Declare a dummy type 'DefaultVoid' which we use +// when we'd like to use 'void'. We convert it into 'void' and back +// using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>. +// Workaround for (2): On VC6, the code for calling a void function is +// identical to the code for calling a non-void function in which the +// return value is never used, provided the return value is returned +// in the EAX register, rather than on the stack. +// This is true for most fundamental types such as int, enum, void *. +// Const void * is the safest option since it doesn't participate +// in any automatic conversions. But on a 16-bit compiler it might +// cause extra code to be generated, so we disable it for all compilers +// except for VC6 (and VC5). +#ifdef FASTDLGT_VC6 +// VC6 workaround +typedef const void * DefaultVoid; +#else +// On any other compiler, just use a normal void. +typedef void DefaultVoid; +#endif + +// Translate from 'DefaultVoid' to 'void'. +// Everything else is unchanged +template +struct DefaultVoidToVoid { typedef T type; }; + +template <> +struct DefaultVoidToVoid { typedef void type; }; + +// Translate from 'void' into 'DefaultVoid' +// Everything else is unchanged +template +struct VoidToDefaultVoid { typedef T type; }; + +template <> +struct VoidToDefaultVoid { typedef DefaultVoid type; }; + + + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 1: +// +// Conversion of member function pointer to a standard form +// +//////////////////////////////////////////////////////////////////////////////// + +// GenericClass is a fake class, ONLY used to provide a type. +// It is vitally important that it is never defined, so that the compiler doesn't +// think it can optimize the invocation. For example, Borland generates simpler +// code if it knows the class only uses single inheritance. + +// Compilers using Microsoft's structure need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS + // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP + // (4 bytes), even when the /vmg option is used. Declaring an empty class + // would give 16 byte pointers in this case.... + class __single_inheritance GenericClass; +#endif + // ...but for Codeplay, an empty class *always* gives 4 byte pointers. + // If compiled with the /clr option ("managed C++"), the JIT compiler thinks + // it needs to load GenericClass before it can call any of its functions, + // (compiles OK but crashes at runtime!), so we need to declare an + // empty class to make it happy. + // Codeplay and VC4 can't cope with the unknown_inheritance case either. + class GenericClass {}; +#else + class GenericClass; +#endif + +// The size of a single inheritance member function pointer. +const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)()); + +// SimplifyMemFunc< >::Convert() +// +// A template function that converts an arbitrary member function pointer into the +// simplest possible form of member function pointer, using a supplied 'this' pointer. +// According to the standard, this can be done legally with reinterpret_cast<>. +// For (non-standard) compilers which use member function pointers which vary in size +// depending on the class, we need to use knowledge of the internal structure of a +// member function pointer, as used by the compiler. Template specialization is used +// to distinguish between the sizes. Because some compilers don't support partial +// template specialisation, I use full specialisation of a wrapper struct. + +// general case -- don't know how to convert it. Force a compile failure +template +struct SimplifyMemFunc { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // Unsupported member function type -- force a compile failure. + // (it's illegal to have a array with negative size). + typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100]; + return 0; + } +}; + +// For compilers where all member func ptrs are the same size, everything goes here. +// For non-standard compilers, only single_inheritance classes go here. +template <> +struct SimplifyMemFunc { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { +#if defined __DMC__ + // Digital Mars doesn't allow you to cast between abitrary PMF's, + // even though the standard says you can. The 32-bit compiler lets you + // static_cast through an int, but the DOS compiler doesn't. + bound_func = horrible_cast(function_to_bind); +#else + bound_func = reinterpret_cast(function_to_bind); +#endif + return reinterpret_cast(pthis); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 1b: +// +// Workarounds for Microsoft and Intel +// +//////////////////////////////////////////////////////////////////////////////// + + +// Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay), +// need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +// We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1) +// at the start of each function for extra safety, but VC6 seems to ICE +// intermittently if you do this inside a template. + +// __multiple_inheritance classes go here +// Nasty hack for Microsoft and Intel (IA32 and Itanium) +template<> +struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) > { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // We need to use a horrible_cast to do this conversion. + // In MSVC, a multiple inheritance member pointer is internally defined as: + union { + XFuncType func; + struct { + GenericMemFuncType funcaddress; // points to the actual member function + int delta; // #BYTES to be added to the 'this' pointer + }s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + return reinterpret_cast(reinterpret_cast(pthis) + u.s.delta); + } +}; + +// virtual inheritance is a real nuisance. It's inefficient and complicated. +// On MSVC and Intel, there isn't enough information in the pointer itself to +// enable conversion to a closure pointer. Earlier versions of this code didn't +// work for all cases, and generated a compile-time error instead. +// But a very clever hack invented by John M. Dlugosz solves this problem. +// My code is somewhat different to his: I have no asm code, and I make no +// assumptions about the calling convention that is used. + +// In VC++ and ICL, a virtual_inheritance member pointer +// is internally defined as: +struct MicrosoftVirtualMFP { + void (GenericClass::*codeptr)(); // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtable_index; // or 0 if no virtual inheritance +}; +// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the +// m_codeptr member is *always* called, regardless of the values of the other +// members. (This is *not* true for other compilers, eg GCC, which obtain the +// function address from the vtable if a virtual function is being called). +// Dlugosz's trick is to make the codeptr point to a probe function which +// returns the 'this' pointer that was used. + +// Define a generic class that uses virtual inheritance. +// It has a trival member function that returns the value of the 'this' pointer. +struct GenericVirtualClass : virtual public GenericClass +{ + typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); + GenericVirtualClass * GetThis() { return this; } +}; + +// __virtual_inheritance classes go here +template <> +struct SimplifyMemFunc +{ + + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + union { + XFuncType func; + GenericClass* (X::*ProbeFunc)(); + MicrosoftVirtualMFP s; + } u; + u.func = function_to_bind; + bound_func = reinterpret_cast(u.s.codeptr); + union { + GenericVirtualClass::ProbePtrType virtfunc; + MicrosoftVirtualMFP s; + } u2; + // Check that the horrible_cast<>s will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s) + && sizeof(function_to_bind)==sizeof(u.ProbeFunc) + && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; + // Unfortunately, taking the address of a MF prevents it from being inlined, so + // this next line can't be completely optimised away by the compiler. + u2.virtfunc = &GenericVirtualClass::GetThis; + u.s.codeptr = u2.s.codeptr; + return (pthis->*u.ProbeFunc)(); + } +}; + +#if (_MSC_VER <1300) + +// Nasty hack for Microsoft Visual C++ 6.0 +// unknown_inheritance classes go here +// There is a compiler bug in MSVC6 which generates incorrect code in this case!! +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // There is an apalling but obscure compiler bug in MSVC6 and earlier: + // vtable_index and 'vtordisp' are always set to 0 in the + // unknown_inheritance case! + // This means that an incorrect function could be called!!! + // Compiling with the /vmg option leads to potentially incorrect code. + // This is probably the reason that the IDE has a user interface for specifying + // the /vmg option, but it is disabled - you can only specify /vmg on + // the command line. In VC1.5 and earlier, the compiler would ICE if it ever + // encountered this situation. + // It is OK to use the /vmg option if /vmm or /vms is specified. + + // Fortunately, the wrong function is only called in very obscure cases. + // It only occurs when a derived class overrides a virtual function declared + // in a virtual base class, and the member function + // points to the *Derived* version of that function. The problem can be + // completely averted in 100% of cases by using the *Base class* for the + // member fpointer. Ie, if you use the base class as an interface, you'll + // stay out of trouble. + // Occasionally, you might want to point directly to a derived class function + // that isn't an override of a base class. In this case, both vtable_index + // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated. + // We can generate correct code in this case. To prevent an incorrect call from + // ever being made, on MSVC6 we generate a warning, and call a function to + // make the program crash instantly. + typedef char ERROR_VC6CompilerBug[-100]; + return 0; + } +}; + + +#else + +// Nasty hack for Microsoft and Intel (IA32 and Itanium) +// unknown_inheritance classes go here +// This is probably the ugliest bit of code I've ever written. Look at the casts! +// There is a compiler bug in MSVC6 which prevents it from using this code. +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // The member function pointer is 16 bytes long. We can't use a normal cast, but + // we can use a union to do the conversion. + union { + XFuncType func; + // In VC++ and ICL, an unknown_inheritance member pointer + // is internally defined as: + struct { + GenericMemFuncType m_funcaddress; // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtordisp; // #bytes to add to 'this' to find the vtable + int vtable_index; // or 0 if no virtual inheritance + } s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + int virtual_delta = 0; + if (u.s.vtable_index) { // Virtual inheritance is used + // First, get to the vtable. + // It is 'vtordisp' bytes from the start of the class. + const int * vtable = *reinterpret_cast( + reinterpret_cast(pthis) + u.s.vtordisp ); + + // 'vtable_index' tells us where in the table we should be looking. + virtual_delta = u.s.vtordisp + *reinterpret_cast( + reinterpret_cast(vtable) + u.s.vtable_index); + } + // The int at 'virtual_delta' gives us the amount to add to 'this'. + // Finally we can add the three components together. Phew! + return reinterpret_cast( + reinterpret_cast(pthis) + u.s.delta + virtual_delta); + }; +}; +#endif // MSVC 7 and greater + +#endif // MS/Intel hacks + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 2: +// +// Define the delegate storage, and cope with static functions +// +//////////////////////////////////////////////////////////////////////////////// + +// DelegateMemento -- an opaque structure which can hold an arbitary delegate. +// It knows nothing about the calling convention or number of arguments used by +// the function pointed to. +// It supplies comparison operators so that it can be stored in STL collections. +// It cannot be set to anything other than null, nor invoked directly: +// it must be converted to a specific delegate. + +// Implementation: +// There are two possible implementations: the Safe method and the Evil method. +// DelegateMemento - Safe version +// +// This implementation is standard-compliant, but a bit tricky. +// A static function pointer is stored inside the class. +// Here are the valid values: +// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+ +// | 0 | 0 | 0 | Empty | +// | !=0 |(dontcare)| Invoker | Static function| +// | 0 | !=0 | !=0* | Method call | +// +--------------------+----------+------------+----------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// When stored stored inside a specific delegate, the 'dontcare' entries are replaced +// with a reference to the delegate itself. This complicates the = and == operators +// for the delegate class. + +// DelegateMemento - Evil version +// +// For compilers where data pointers are at least as big as code pointers, it is +// possible to store the function pointer in the this pointer, using another +// horrible_cast. In this case the DelegateMemento implementation is simple: +// +--pThis --+-- pMemFunc-+-- Meaning---------------------+ +// | 0 | 0 | Empty | +// | !=0 | !=0* | Static function or method call| +// +----------+------------+-------------------------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// Note that the Sun C++ and MSVC documentation explicitly state that they +// support static_cast between void * and function pointers. + +class DelegateMemento { +protected: + // the data is protected, not private, because many + // compilers have problems with template friends. + typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP. + detail::GenericClass *m_pthis; + GenericMemFuncType m_pFunction; + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + typedef void (*GenericFuncPtr)(); // arbitrary code pointer + GenericFuncPtr m_pStaticFunction; +#endif + +public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {}; + void clear() { + m_pthis=0; m_pFunction=0; m_pStaticFunction=0; + } +#else + DelegateMemento() : m_pthis(0), m_pFunction(0) {}; + void clear() { m_pthis=0; m_pFunction=0; } +#endif +public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + inline bool IsEqual (const DelegateMemento &x) const{ + // We have to cope with the static function pointers as a special case + if (m_pFunction!=x.m_pFunction) return false; + // the static function ptrs must either both be equal, or both be 0. + if (m_pStaticFunction!=x.m_pStaticFunction) return false; + if (m_pStaticFunction!=0) return m_pthis==x.m_pthis; + else return true; + } +#else // Evil Method + inline bool IsEqual (const DelegateMemento &x) const{ + return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction; + } +#endif + // Provide a strict weak ordering for DelegateMementos. + inline bool IsLess(const DelegateMemento &right) const { + // deal with static function pointers first +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0) + return m_pStaticFunction < right.m_pStaticFunction; +#endif + if (m_pthis !=right.m_pthis) return m_pthis < right.m_pthis; + // There are no ordering operators for member function pointers, + // but we can fake one by comparing each byte. The resulting ordering is + // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers. + return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0; + + } + // BUGFIX (Mar 2005): + // We can't just compare m_pFunction because on Metrowerks, + // m_pFunction can be zero even if the delegate is not empty! + inline bool operator ! () const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } + inline bool empty() const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } +public: + DelegateMemento & operator = (const DelegateMemento &right) { + SetMementoFrom(right); + return *this; + } + inline bool operator <(const DelegateMemento &right) { + return IsLess(right); + } + inline bool operator >(const DelegateMemento &right) { + return right.IsLess(*this); + } + DelegateMemento (const DelegateMemento &right) : + m_pthis(right.m_pthis), m_pFunction(right.m_pFunction) +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + , m_pStaticFunction (right.m_pStaticFunction) +#endif + {} +protected: + void SetMementoFrom(const DelegateMemento &right) { + m_pFunction = right.m_pFunction; + m_pthis = right.m_pthis; +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = right.m_pStaticFunction; +#endif + } +}; + + +// ClosurePtr<> +// +// A private wrapper class that adds function signatures to DelegateMemento. +// It's the class that does most of the actual work. +// The signatures are specified by: +// GenericMemFunc: must be a type of GenericClass member function pointer. +// StaticFuncPtr: must be a type of function pointer with the same signature +// as GenericMemFunc. +// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6 +// where it never returns void (returns DefaultVoid instead). + +// An outer class, FastDelegateN<>, handles the invoking and creates the +// necessary typedefs. +// This class does everything else. + +namespace detail { + +template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr> +class ClosurePtr : public DelegateMemento { +public: + // These functions are for setting the delegate to a member function. + + // Here's the clever bit: we convert an arbitrary member function into a + // standard form. XMemFunc should be a member function of class X, but I can't + // enforce that here. It needs to be enforced by the wrapper class. + template < class X, class XMemFunc > + inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) { + m_pthis = SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(pthis, function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } + // For const member functions, we only need a const class pointer. + // Since we know that the member function is const, it's safe to + // remove the const qualifier from the 'this' pointer with a const_cast. + // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name. + template < class X, class XMemFunc> + inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) { + m_pthis= SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(const_cast(pthis), function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates + template < class X, class XMemFunc> + inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) { + bindconstmemfunc(pthis, function_to_bind); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#endif + // These functions are required for invoking the stored function + inline GenericClass *GetClosureThis() const { return m_pthis; } + inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast(m_pFunction); } + +// There are a few ways of dealing with static function pointers. +// There's a standard-compliant, but tricky method. +// There's also a straightforward hack, that won't work on DOS compilers using the +// medium memory model. It's so evil that I can't recommend it, but I've +// implemented it anyway because it produces very nice asm code. + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + +// ClosurePtr<> - Safe version +// +// This implementation is standard-compliant, but a bit tricky. +// I store the function pointer inside the class, and the delegate then +// points to itself. Whenever the delegate is copied, these self-references +// must be transformed, and this complicates the = and == operators. +public: + // The next two functions are for operator ==, =, and the copy constructor. + // We may need to convert the m_pthis pointers, so that + // they remain as self-references. + template< class DerivedClass > + inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &x) { + SetMementoFrom(x); + if (m_pStaticFunction!=0) { + // transform self references... + m_pthis=reinterpret_cast(pParent); + } + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + template < class DerivedClass, class ParentInvokerSig > + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind ) { + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + bindmemfunc(pParent, static_function_invoker); + } + m_pStaticFunction=reinterpret_cast(function_to_bind); + } + inline UnvoidStaticFuncPtr GetStaticFunction() const { + return reinterpret_cast(m_pStaticFunction); + } +#else + +// ClosurePtr<> - Evil version +// +// For compilers where data pointers are at least as big as code pointers, it is +// possible to store the function pointer in the this pointer, using another +// horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and +// speeds up comparison and assignment. If C++ provided direct language support +// for delegates, they would produce asm code that was almost identical to this. +// Note that the Sun C++ and MSVC documentation explicitly state that they +// support static_cast between void * and function pointers. + + template< class DerivedClass > + inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &right) { + SetMementoFrom(right); + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + // ******** EVIL, EVIL CODE! ******* + template < class DerivedClass, class ParentInvokerSig> + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind) { + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + // We'll be ignoring the 'this' pointer, but we need to make sure we pass + // a valid value to bindmemfunc(). + bindmemfunc(pParent, static_function_invoker); + } + + // WARNING! Evil hack. We store the function in the 'this' pointer! + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1]; + m_pthis = horrible_cast(function_to_bind); + // MSVC, SunC++ and DMC accept the following (non-standard) code: +// m_pthis = static_cast(static_cast(function_to_bind)); + // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long +// m_pthis = reinterpret_cast(reinterpret_cast(function_to_bind)); + } + // ******** EVIL, EVIL CODE! ******* + // This function will be called with an invalid 'this' pointer!! + // We're just returning the 'this' pointer, converted into + // a function pointer! + inline UnvoidStaticFuncPtr GetStaticFunction() const { + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1]; + return horrible_cast(this); + } +#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + + // Does the closure contain this static function? + inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){ + if (funcptr==0) return empty(); + // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary + // value that is not equal to any valid function pointer. + else return funcptr==reinterpret_cast(GetStaticFunction()); + } +}; + + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 3: +// +// Wrapper classes to ensure type safety +// +//////////////////////////////////////////////////////////////////////////////// + + +// Once we have the member function conversion templates, it's easy to make the +// wrapper classes. So that they will work with as many compilers as possible, +// the classes are of the form +// FastDelegate3 +// They can cope with any combination of parameters. The max number of parameters +// allowed is 8, but it is trivial to increase this limit. +// Note that we need to treat const member functions seperately. +// All this class does is to enforce type safety, and invoke the delegate with +// the correct list of parameters. + +// Because of the weird rule about the class of derived member function pointers, +// you sometimes need to apply a downcast to the 'this' pointer. +// This is the reason for the use of "implicit_cast(pthis)" in the code below. +// If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction, +// without this trick you'd need to write: +// MyDelegate(static_cast(&d), &CDerivedClass::SimpleVirtualFunction); +// but with the trick you can write +// MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction); + +// RetType is the type the compiler uses in compiling the template. For VC6, +// it cannot be void. DesiredRetType is the real type which is returned from +// all of the functions. It can be void. + +// Implicit conversion to "bool" is achieved using the safe_bool idiom, +// using member data pointers (MDP). This allows "if (dg)..." syntax +// Because some compilers (eg codeplay) don't have a unique value for a zero +// MDP, an extra padding member is added to the SafeBool struct. +// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so +// in that case the static function constructor is not made explicit; this +// allows "if (dg==0) ..." to compile. + +//N=0 +template +class FastDelegate0 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(); + typedef RetType (*UnvoidStaticFunctionPtr)(); + typedef RetType (detail::GenericClass::*GenericMemFn)(); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate0 type; + + // Construction and comparison functions + FastDelegate0() { clear(); } + FastDelegate0(const FastDelegate0 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate0 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate0 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate0 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate0 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate0 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate0(Y *pthis, DesiredRetType (X::* function_to_bind)() ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)()) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate0(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate0(DesiredRetType (*function_to_bind)() ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)() ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)()) { + m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() () const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction() const { + return (*(m_Closure.GetStaticFunction()))(); } +}; + +//N=1 +template +class FastDelegate1 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate1 type; + + // Construction and comparison functions + FastDelegate1() { clear(); } + FastDelegate1(const FastDelegate1 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate1 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate1 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate1 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate1 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate1 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate1(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate1(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1)) { + m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1) const { + return (*(m_Closure.GetStaticFunction()))(p1); } +}; + +//N=2 +template +class FastDelegate2 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate2 type; + + // Construction and comparison functions + FastDelegate2() { clear(); } + FastDelegate2(const FastDelegate2 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate2 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate2 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate2 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate2 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate2 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate2(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate2(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2)) { + m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2); } +}; + +//N=3 +template +class FastDelegate3 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate3 type; + + // Construction and comparison functions + FastDelegate3() { clear(); } + FastDelegate3(const FastDelegate3 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate3 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate3 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate3 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate3 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate3 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate3(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate3(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3); } +}; + +//N=4 +template +class FastDelegate4 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate4 type; + + // Construction and comparison functions + FastDelegate4() { clear(); } + FastDelegate4(const FastDelegate4 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate4 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate4 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate4 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate4 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate4 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate4(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate4(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4); } +}; + +//N=5 +template +class FastDelegate5 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate5 type; + + // Construction and comparison functions + FastDelegate5() { clear(); } + FastDelegate5(const FastDelegate5 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate5 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate5 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate5 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate5 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate5 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate5(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate5(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5); } +}; + +//N=6 +template +class FastDelegate6 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate6 type; + + // Construction and comparison functions + FastDelegate6() { clear(); } + FastDelegate6(const FastDelegate6 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate6 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate6 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate6 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate6 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate6 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate6(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate6(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6); } +}; + +//N=7 +template +class FastDelegate7 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate7 type; + + // Construction and comparison functions + FastDelegate7() { clear(); } + FastDelegate7(const FastDelegate7 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate7 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate7 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate7 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate7 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate7 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate7(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate7(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7); } +}; + +//N=8 +template +class FastDelegate8 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate8 type; + + // Construction and comparison functions + FastDelegate8() { clear(); } + FastDelegate8(const FastDelegate8 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate8 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate8 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate8 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate8 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate8 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate8(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate8(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8); } +}; + +//N=9 +template +class FastDelegate9 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate9 type; + + // Construction and comparison functions + FastDelegate9() { clear(); } + FastDelegate9(const FastDelegate9 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate9 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate9 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate9 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate9 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate9 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate9(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate9(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate9(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { + m_Closure.bindstaticfunc(this, &FastDelegate9::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9); } +}; + +//N=10 +template +class FastDelegate10 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate10 type; + + // Construction and comparison functions + FastDelegate10() { clear(); } + FastDelegate10(const FastDelegate10 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate10 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate10 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate10 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate10 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate10 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate10(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate10(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate10(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { + m_Closure.bindstaticfunc(this, &FastDelegate10::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } +}; + +//N=11 +template +class FastDelegate11 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate11 type; + + // Construction and comparison functions + FastDelegate11() { clear(); } + FastDelegate11(const FastDelegate11 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate11 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate11 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate11 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate11 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate11 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate11(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate11(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate11(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + m_Closure.bindstaticfunc(this, &FastDelegate11::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } +}; + +//N=12 +template +class FastDelegate12 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate12 type; + + // Construction and comparison functions + FastDelegate12() { clear(); } + FastDelegate12(const FastDelegate12 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate12 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate12 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate12 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate12 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate12 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate12(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate12(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate12(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + m_Closure.bindstaticfunc(this, &FastDelegate12::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } +}; + +//N=13 +template +class FastDelegate13 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate13 type; + + // Construction and comparison functions + FastDelegate13() { clear(); } + FastDelegate13(const FastDelegate13 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate13 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate13 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate13 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate13 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate13 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate13(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate13(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate13(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + m_Closure.bindstaticfunc(this, &FastDelegate13::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } +}; + +//N=14 +template +class FastDelegate14 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate14 type; + + // Construction and comparison functions + FastDelegate14() { clear(); } + FastDelegate14(const FastDelegate14 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate14 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate14 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate14 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate14 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate14 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate14(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate14(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate14(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { + m_Closure.bindstaticfunc(this, &FastDelegate14::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); } +}; + +//N=15 +template +class FastDelegate15 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate15 type; + + // Construction and comparison functions + FastDelegate15() { clear(); } + FastDelegate15(const FastDelegate15 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate15 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate15 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate15 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate15 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate15 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate15(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate15(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate15(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { + m_Closure.bindstaticfunc(this, &FastDelegate15::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); } +}; + +//N=16 +template +class FastDelegate16 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate16 type; + + // Construction and comparison functions + FastDelegate16() { clear(); } + FastDelegate16(const FastDelegate16 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate16 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate16 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate16 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate16 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate16 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate16(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate16(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate16(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { + m_Closure.bindstaticfunc(this, &FastDelegate16::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16); } +}; + +//N=17 +template +class FastDelegate17 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate17 type; + + // Construction and comparison functions + FastDelegate17() { clear(); } + FastDelegate17(const FastDelegate17 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate17 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate17 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate17 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate17 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate17 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate17(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate17(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate17(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { + m_Closure.bindstaticfunc(this, &FastDelegate17::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17); } +}; + +//N=18 +template +class FastDelegate18 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate18 type; + + // Construction and comparison functions + FastDelegate18() { clear(); } + FastDelegate18(const FastDelegate18 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate18 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate18 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate18 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate18 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate18 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate18(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate18(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate18(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { + m_Closure.bindstaticfunc(this, &FastDelegate18::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18); } +}; + +//N=19 +template +class FastDelegate19 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate19 type; + + // Construction and comparison functions + FastDelegate19() { clear(); } + FastDelegate19(const FastDelegate19 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate19 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate19 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate19 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate19 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate19 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate19(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate19(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate19(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { + m_Closure.bindstaticfunc(this, &FastDelegate19::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19); } +}; + +//N=20 +template +class FastDelegate20 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate20 type; + + // Construction and comparison functions + FastDelegate20() { clear(); } + FastDelegate20(const FastDelegate20 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate20 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate20 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate20 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate20 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate20 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate20(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate20(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate20(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { + m_Closure.bindstaticfunc(this, &FastDelegate20::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20); } +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 4: +// +// FastDelegate<> class (Original author: Jody Hagins) +// Allows boost::function style syntax like: +// FastDelegate< double (int, long) > +// instead of: +// FastDelegate2< int, long, double > +// +//////////////////////////////////////////////////////////////////////////////// + +#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +// Declare FastDelegate as a class template. It will be specialized +// later for all number of arguments. +template +class FastDelegate; + +//N=0 +// Specialization to allow use of +// FastDelegate< R ( ) > +// instead of +// FastDelegate0 < R > +template +class FastDelegate< R ( ) > + // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0 + : public FastDelegate0 < R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate0 < R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=1 +// Specialization to allow use of +// FastDelegate< R ( Param1 ) > +// instead of +// FastDelegate1 < Param1, R > +template +class FastDelegate< R ( Param1 ) > + // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1 + : public FastDelegate1 < Param1, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate1 < Param1, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=2 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2 ) > +// instead of +// FastDelegate2 < Param1, Param2, R > +template +class FastDelegate< R ( Param1, Param2 ) > + // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2 + : public FastDelegate2 < Param1, Param2, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate2 < Param1, Param2, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=3 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3 ) > +// instead of +// FastDelegate3 < Param1, Param2, Param3, R > +template +class FastDelegate< R ( Param1, Param2, Param3 ) > + // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3 + : public FastDelegate3 < Param1, Param2, Param3, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate3 < Param1, Param2, Param3, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=4 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4 ) > +// instead of +// FastDelegate4 < Param1, Param2, Param3, Param4, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4 ) > + // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4 + : public FastDelegate4 < Param1, Param2, Param3, Param4, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate4 < Param1, Param2, Param3, Param4, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=5 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > +// instead of +// FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > + // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5 + : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=6 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > +// instead of +// FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > + // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6 + : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=7 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > +// instead of +// FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > + // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7 + : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=8 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > +// instead of +// FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > + // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8 + : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=9 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9 ) > +// instead of +// FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9 ) > + // Inherit from FastDelegate9 so that it can be treated just like a FastDelegate9 + : public FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=10 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10 ) > +// instead of +// FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10 ) > + // Inherit from FastDelegate10 so that it can be treated just like a FastDelegate10 + : public FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=11 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11 ) > +// instead of +// FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11 ) > + // Inherit from FastDelegate11 so that it can be treated just like a FastDelegate11 + : public FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=12 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12 ) > +// instead of +// FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12 ) > + // Inherit from FastDelegate12 so that it can be treated just like a FastDelegate12 + : public FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=13 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13 ) > +// instead of +// FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13 ) > + // Inherit from FastDelegate13 so that it can be treated just like a FastDelegate13 + : public FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=14 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14 ) > +// instead of +// FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14 ) > + // Inherit from FastDelegate14 so that it can be treated just like a FastDelegate14 + : public FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=15 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15 ) > +// instead of +// FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15 ) > + // Inherit from FastDelegate15 so that it can be treated just like a FastDelegate15 + : public FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=16 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16 ) > +// instead of +// FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16 ) > + // Inherit from FastDelegate16 so that it can be treated just like a FastDelegate16 + : public FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=17 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17 ) > +// instead of +// FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17 ) > + // Inherit from FastDelegate17 so that it can be treated just like a FastDelegate17 + : public FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=18 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18 ) > +// instead of +// FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18 ) > + // Inherit from FastDelegate18 so that it can be treated just like a FastDelegate18 + : public FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=19 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19 ) > +// instead of +// FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19 ) > + // Inherit from FastDelegate19 so that it can be treated just like a FastDelegate19 + : public FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=20 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20 ) > +// instead of +// FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20 ) > + // Inherit from FastDelegate20 so that it can be treated just like a FastDelegate20 + : public FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + + +#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 5: +// +// MakeDelegate() helper function +// +// MakeDelegate(&x, &X::func) returns a fastdelegate of the type +// necessary for calling x.func() with the correct number of arguments. +// This makes it possible to eliminate many typedefs from user code. +// +//////////////////////////////////////////////////////////////////////////////// + +// Also declare overloads of a MakeDelegate() global function to +// reduce the need for typedefs. +// We need seperate overloads for const and non-const member functions. +// Also, because of the weird rule about the class of derived member function pointers, +// implicit downcasts may need to be applied later to the 'this' pointer. +// That's why two classes (X and Y) appear in the definitions. Y must be implicitly +// castable to X. + +// Workaround for VC6. VC6 needs void return types converted into DefaultVoid. +// GCC 3.2 and later won't compile this unless it's preceded by 'typename', +// but VC6 doesn't allow 'typename' in this context. +// So, I have to use a macro. + +#ifdef FASTDLGT_VC6 +#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid::type +#else +#define FASTDLGT_RETTYPE RetType +#endif + +//N=0 +template +FastDelegate0 MakeDelegate(Y* x, RetType (X::*func)()) { + return FastDelegate0(x, func); +} + +template +FastDelegate0 MakeDelegate(Y* x, RetType (X::*func)() const) { + return FastDelegate0(x, func); +} + +template +FastDelegate0 MakeDelegate(RetType (*func)()) { + return FastDelegate0(func); +} + +//N=1 +template +FastDelegate1 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1)) { + return FastDelegate1(x, func); +} + +template +FastDelegate1 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1) const) { + return FastDelegate1(x, func); +} + +template +FastDelegate1 MakeDelegate(RetType (*func)(Param1 p1)) { + return FastDelegate1(func); +} + +//N=2 +template +FastDelegate2 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2)) { + return FastDelegate2(x, func); +} + +template +FastDelegate2 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2) const) { + return FastDelegate2(x, func); +} + +template +FastDelegate2 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2)) { + return FastDelegate2(func); +} + +//N=3 +template +FastDelegate3 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3)) { + return FastDelegate3(x, func); +} + +template +FastDelegate3 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3) const) { + return FastDelegate3(x, func); +} + +template +FastDelegate3 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3)) { + return FastDelegate3(func); +} + +//N=4 +template +FastDelegate4 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + return FastDelegate4(x, func); +} + +template +FastDelegate4 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + return FastDelegate4(x, func); +} + +template +FastDelegate4 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + return FastDelegate4(func); +} + +//N=5 +template +FastDelegate5 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + return FastDelegate5(x, func); +} + +template +FastDelegate5 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + return FastDelegate5(x, func); +} + +template +FastDelegate5 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + return FastDelegate5(func); +} + +//N=6 +template +FastDelegate6 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + return FastDelegate6(x, func); +} + +template +FastDelegate6 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + return FastDelegate6(x, func); +} + +template +FastDelegate6 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + return FastDelegate6(func); +} + +//N=7 +template +FastDelegate7 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + return FastDelegate7(x, func); +} + +template +FastDelegate7 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + return FastDelegate7(x, func); +} + +template +FastDelegate7 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + return FastDelegate7(func); +} + +//N=8 +template +FastDelegate8 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + return FastDelegate8(x, func); +} + +template +FastDelegate8 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + return FastDelegate8(x, func); +} + +template +FastDelegate8 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + return FastDelegate8(func); +} + +//N=9 +template +FastDelegate9 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { + return FastDelegate9(x, func); +} + +template +FastDelegate9 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const) { + return FastDelegate9(x, func); +} + +template +FastDelegate9 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { + return FastDelegate9(func); +} + +//N=10 +template +FastDelegate10 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { + return FastDelegate10(x, func); +} + +template +FastDelegate10 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const) { + return FastDelegate10(x, func); +} + +template +FastDelegate10 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { + return FastDelegate10(func); +} + +//N=11 +template +FastDelegate11 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + return FastDelegate11(x, func); +} + +template +FastDelegate11 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { + return FastDelegate11(x, func); +} + +template +FastDelegate11 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + return FastDelegate11(func); +} + +//N=12 +template +FastDelegate12 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + return FastDelegate12(x, func); +} + +template +FastDelegate12 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { + return FastDelegate12(x, func); +} + +template +FastDelegate12 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + return FastDelegate12(func); +} + +//N=13 +template +FastDelegate13 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + return FastDelegate13(x, func); +} + +template +FastDelegate13 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { + return FastDelegate13(x, func); +} + +template +FastDelegate13 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + return FastDelegate13(func); +} + +//N=14 +template +FastDelegate14 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { + return FastDelegate14(x, func); +} + +template +FastDelegate14 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const) { + return FastDelegate14(x, func); +} + +template +FastDelegate14 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { + return FastDelegate14(func); +} + +//N=15 +template +FastDelegate15 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { + return FastDelegate15(x, func); +} + +template +FastDelegate15 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const) { + return FastDelegate15(x, func); +} + +template +FastDelegate15 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { + return FastDelegate15(func); +} + +//N=16 +template +FastDelegate16 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { + return FastDelegate16(x, func); +} + +template +FastDelegate16 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const) { + return FastDelegate16(x, func); +} + +template +FastDelegate16 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { + return FastDelegate16(func); +} + +//N=17 +template +FastDelegate17 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { + return FastDelegate17(x, func); +} + +template +FastDelegate17 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const) { + return FastDelegate17(x, func); +} + +template +FastDelegate17 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { + return FastDelegate17(func); +} + +//N=18 +template +FastDelegate18 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { + return FastDelegate18(x, func); +} + +template +FastDelegate18 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const) { + return FastDelegate18(x, func); +} + +template +FastDelegate18 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { + return FastDelegate18(func); +} + +//N=19 +template +FastDelegate19 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { + return FastDelegate19(x, func); +} + +template +FastDelegate19 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const) { + return FastDelegate19(x, func); +} + +template +FastDelegate19 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { + return FastDelegate19(func); +} + +//N=20 +template +FastDelegate20 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { + return FastDelegate20(x, func); +} + +template +FastDelegate20 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const) { + return FastDelegate20(x, func); +} + +template +FastDelegate20 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { + return FastDelegate20(func); +} + + + // clean up after ourselves... +#undef FASTDLGT_RETTYPE + +} // namespace fastdelegate + +#endif // !defined(FASTDELEGATE_H) diff --git a/utils/mmsource/core-legacy/sourcehook/generate/FastDelegate.h b/utils/mmsource/core-legacy/sourcehook/generate/FastDelegate.h new file mode 100644 index 00000000..a17bb1a3 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/FastDelegate.h @@ -0,0 +1,3811 @@ +// FastDelegate.h +// Efficient delegates in C++ that generate only two lines of asm code! +// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp +// +// - Don Clugston, Mar 2004. +// Major contributions were made by Jody Hagins. +// History: +// 24-Apr-04 1.0 * Submitted to CodeProject. +// 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack. +// * Improved syntax for horrible_cast (thanks Paul Bludov). +// * Tested on Metrowerks MWCC and Intel ICL (IA32) +// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL. +// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5 +// * Now works on /clr "managed C++" code on VC7, VC7.1 +// * Comeau C++ now compiles without warnings. +// * Prevent the virtual inheritance case from being used on +// VC6 and earlier, which generate incorrect code. +// * Improved warning and error messages. Non-standard hacks +// now have compile-time checks to make them safer. +// * implicit_cast used instead of static_cast in many cases. +// * If calling a const member function, a const class pointer can be used. +// * MakeDelegate() global helper function added to simplify pass-by-value. +// * Added fastdelegate.clear() +// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates) +// 30-Oct-04 1.3 * Support for (non-void) return values. +// * No more workarounds in client code! +// MSVC and Intel now use a clever hack invented by John Dlugosz: +// - The FASTDELEGATEDECLARE workaround is no longer necessary. +// - No more warning messages for VC6 +// * Less use of macros. Error messages should be more comprehensible. +// * Added include guards +// * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks). +// * Now tested on VS 2005 Express Beta, PGI C++ +// 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates. +// * <,>,<=,>= comparison operators to allow storage in ordered containers. +// * Substantial reduction of code size, especially the 'Closure' class. +// * Standardised all the compiler-specific workarounds. +// * MFP conversion now works for CodePlay (but not yet supported in the full code). +// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1 +// * New syntax: FastDelegate< int (char *, double) >. +// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric). +// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium. +// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())" +// * Fully supported by CodePlay VectorC +// * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC! +// * More optimal assignment,== and != operators for static function pointers. + +#ifndef FASTDELEGATE_H +#define FASTDELEGATE_H + +#ifdef _MSC_VER +# if _MSC_VER > 1000 +# pragma once +# endif // _MSC_VER > 1000 +#endif // #ifdef _MSC_VER + +#include // to allow <,> comparisons + +//////////////////////////////////////////////////////////////////////////////// +// Configuration options +// +//////////////////////////////////////////////////////////////////////////////// + +// Uncomment the following #define for optimally-sized delegates. +// In this case, the generated asm code is almost identical to the code you'd get +// if the compiler had native support for delegates. +// It will not work on systems where sizeof(dataptr) < sizeof(codeptr). +// Thus, it will not work for DOS compilers using the medium model. +// It will also probably fail on some DSP systems. +#define FASTDELEGATE_USESTATICFUNCTIONHACK + +// Uncomment the next line to allow function declarator syntax. +// It is automatically enabled for those compilers where it is known to work. +//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Compiler identification for workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Compiler identification. It's not easy to identify Visual C++ because +// many vendors fraudulently define Microsoft's identifiers. +#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__) +#define FASTDLGT_ISMSVC + +#if (_MSC_VER <1300) // Many workarounds are required for VC6. +#define FASTDLGT_VC6 +#pragma warning(disable:4786) // disable this ridiculous warning +#endif + +#endif + +// Does the compiler uses Microsoft's member function pointer structure? +// If so, it needs special treatment. +// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's +// identifier, _MSC_VER. We need to filter Metrowerks out. +#if defined(_MSC_VER) && !defined(__MWERKS__) +#define FASTDLGT_MICROSOFT_MFP + +#if !defined(__VECTOR_C) +// CodePlay doesn't have the __single/multi/virtual_inheritance keywords +#define FASTDLGT_HASINHERITANCE_KEYWORDS +#endif +#endif + +// Does it allow function declarator syntax? The following compilers are known to work: +#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1 +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use. +#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too. +#if defined (__MWERKS__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +#ifdef __GNUC__ // Workaround GCC bug #8271 + // At present, GCC doesn't recognize constness of MFPs in templates +#define FASTDELEGATE_GCC_BUG_8271 +#endif + + + +//////////////////////////////////////////////////////////////////////////////// +// General tricks used in this code +// +// (a) Error messages are generated by typdefing an array of negative size to +// generate compile-time errors. +// (b) Warning messages on MSVC are generated by declaring unused variables, and +// enabling the "variable XXX is never used" warning. +// (c) Unions are used in a few compiler-specific cases to perform illegal casts. +// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to +// (char *) first to ensure that the correct number of *bytes* are added. +// +//////////////////////////////////////////////////////////////////////////////// +// Helper templates +// +//////////////////////////////////////////////////////////////////////////////// + + +namespace fastdelegate { +namespace detail { // we'll hide the implementation details in a nested namespace. + +// implicit_cast< > +// I believe this was originally going to be in the C++ standard but +// was left out by accident. It's even milder than static_cast. +// I use it instead of static_cast<> to emphasize that I'm not doing +// anything nasty. +// Usage is identical to static_cast<> +template +inline OutputClass implicit_cast(InputClass input){ + return input; +} + +// horrible_cast< > +// This is truly evil. It completely subverts C++'s type system, allowing you +// to cast from any class to any other class. Technically, using a union +// to perform the cast is undefined behaviour (even in C). But we can see if +// it is OK by checking that the union is the same size as each of its members. +// horrible_cast<> should only be used for compiler-specific workarounds. +// Usage is identical to reinterpret_cast<>. + +// This union is declared outside the horrible_cast because BCC 5.5.1 +// can't inline a function with a nested class, and gives a warning. +template +union horrible_union{ + OutputClass out; + InputClass in; +}; + +template +inline OutputClass horrible_cast(const InputClass input){ + horrible_union u; + // Cause a compile-time error if in, out and u are not the same size. + // If the compile fails here, it means the compiler has peculiar + // unions which would prevent the cast from working. + typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) + && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1]; + u.in = input; + return u.out; +} + +//////////////////////////////////////////////////////////////////////////////// +// Workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Backwards compatibility: This macro used to be necessary in the virtual inheritance +// case for Intel and Microsoft. Now it just forward-declares the class. +#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME; + +// Prevent use of the static function hack with the DOS medium model. +#ifdef __MEDIUM__ +#undef FASTDELEGATE_USESTATICFUNCTIONHACK +#endif + +// DefaultVoid - a workaround for 'void' templates in VC6. +// +// (1) VC6 and earlier do not allow 'void' as a default template argument. +// (2) They also doesn't allow you to return 'void' from a function. +// +// Workaround for (1): Declare a dummy type 'DefaultVoid' which we use +// when we'd like to use 'void'. We convert it into 'void' and back +// using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>. +// Workaround for (2): On VC6, the code for calling a void function is +// identical to the code for calling a non-void function in which the +// return value is never used, provided the return value is returned +// in the EAX register, rather than on the stack. +// This is true for most fundamental types such as int, enum, void *. +// Const void * is the safest option since it doesn't participate +// in any automatic conversions. But on a 16-bit compiler it might +// cause extra code to be generated, so we disable it for all compilers +// except for VC6 (and VC5). +#ifdef FASTDLGT_VC6 +// VC6 workaround +typedef const void * DefaultVoid; +#else +// On any other compiler, just use a normal void. +typedef void DefaultVoid; +#endif + +// Translate from 'DefaultVoid' to 'void'. +// Everything else is unchanged +template +struct DefaultVoidToVoid { typedef T type; }; + +template <> +struct DefaultVoidToVoid { typedef void type; }; + +// Translate from 'void' into 'DefaultVoid' +// Everything else is unchanged +template +struct VoidToDefaultVoid { typedef T type; }; + +template <> +struct VoidToDefaultVoid { typedef DefaultVoid type; }; + + + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 1: +// +// Conversion of member function pointer to a standard form +// +//////////////////////////////////////////////////////////////////////////////// + +// GenericClass is a fake class, ONLY used to provide a type. +// It is vitally important that it is never defined, so that the compiler doesn't +// think it can optimize the invocation. For example, Borland generates simpler +// code if it knows the class only uses single inheritance. + +// Compilers using Microsoft's structure need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS + // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP + // (4 bytes), even when the /vmg option is used. Declaring an empty class + // would give 16 byte pointers in this case.... + class __single_inheritance GenericClass; +#endif + // ...but for Codeplay, an empty class *always* gives 4 byte pointers. + // If compiled with the /clr option ("managed C++"), the JIT compiler thinks + // it needs to load GenericClass before it can call any of its functions, + // (compiles OK but crashes at runtime!), so we need to declare an + // empty class to make it happy. + // Codeplay and VC4 can't cope with the unknown_inheritance case either. + class GenericClass {}; +#else + class GenericClass; +#endif + +// The size of a single inheritance member function pointer. +const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)()); + +// SimplifyMemFunc< >::Convert() +// +// A template function that converts an arbitrary member function pointer into the +// simplest possible form of member function pointer, using a supplied 'this' pointer. +// According to the standard, this can be done legally with reinterpret_cast<>. +// For (non-standard) compilers which use member function pointers which vary in size +// depending on the class, we need to use knowledge of the internal structure of a +// member function pointer, as used by the compiler. Template specialization is used +// to distinguish between the sizes. Because some compilers don't support partial +// template specialisation, I use full specialisation of a wrapper struct. + +// general case -- don't know how to convert it. Force a compile failure +template +struct SimplifyMemFunc { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // Unsupported member function type -- force a compile failure. + // (it's illegal to have a array with negative size). + typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100]; + return 0; + } +}; + +// For compilers where all member func ptrs are the same size, everything goes here. +// For non-standard compilers, only single_inheritance classes go here. +template <> +struct SimplifyMemFunc { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { +#if defined __DMC__ + // Digital Mars doesn't allow you to cast between abitrary PMF's, + // even though the standard says you can. The 32-bit compiler lets you + // static_cast through an int, but the DOS compiler doesn't. + bound_func = horrible_cast(function_to_bind); +#else + bound_func = reinterpret_cast(function_to_bind); +#endif + return reinterpret_cast(pthis); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 1b: +// +// Workarounds for Microsoft and Intel +// +//////////////////////////////////////////////////////////////////////////////// + + +// Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay), +// need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +// We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1) +// at the start of each function for extra safety, but VC6 seems to ICE +// intermittently if you do this inside a template. + +// __multiple_inheritance classes go here +// Nasty hack for Microsoft and Intel (IA32 and Itanium) +template<> +struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) > { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // We need to use a horrible_cast to do this conversion. + // In MSVC, a multiple inheritance member pointer is internally defined as: + union { + XFuncType func; + struct { + GenericMemFuncType funcaddress; // points to the actual member function + int delta; // #BYTES to be added to the 'this' pointer + }s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + return reinterpret_cast(reinterpret_cast(pthis) + u.s.delta); + } +}; + +// virtual inheritance is a real nuisance. It's inefficient and complicated. +// On MSVC and Intel, there isn't enough information in the pointer itself to +// enable conversion to a closure pointer. Earlier versions of this code didn't +// work for all cases, and generated a compile-time error instead. +// But a very clever hack invented by John M. Dlugosz solves this problem. +// My code is somewhat different to his: I have no asm code, and I make no +// assumptions about the calling convention that is used. + +// In VC++ and ICL, a virtual_inheritance member pointer +// is internally defined as: +struct MicrosoftVirtualMFP { + void (GenericClass::*codeptr)(); // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtable_index; // or 0 if no virtual inheritance +}; +// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the +// m_codeptr member is *always* called, regardless of the values of the other +// members. (This is *not* true for other compilers, eg GCC, which obtain the +// function address from the vtable if a virtual function is being called). +// Dlugosz's trick is to make the codeptr point to a probe function which +// returns the 'this' pointer that was used. + +// Define a generic class that uses virtual inheritance. +// It has a trival member function that returns the value of the 'this' pointer. +struct GenericVirtualClass : virtual public GenericClass +{ + typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); + GenericVirtualClass * GetThis() { return this; } +}; + +// __virtual_inheritance classes go here +template <> +struct SimplifyMemFunc +{ + + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + union { + XFuncType func; + GenericClass* (X::*ProbeFunc)(); + MicrosoftVirtualMFP s; + } u; + u.func = function_to_bind; + bound_func = reinterpret_cast(u.s.codeptr); + union { + GenericVirtualClass::ProbePtrType virtfunc; + MicrosoftVirtualMFP s; + } u2; + // Check that the horrible_cast<>s will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s) + && sizeof(function_to_bind)==sizeof(u.ProbeFunc) + && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; + // Unfortunately, taking the address of a MF prevents it from being inlined, so + // this next line can't be completely optimised away by the compiler. + u2.virtfunc = &GenericVirtualClass::GetThis; + u.s.codeptr = u2.s.codeptr; + return (pthis->*u.ProbeFunc)(); + } +}; + +#if (_MSC_VER <1300) + +// Nasty hack for Microsoft Visual C++ 6.0 +// unknown_inheritance classes go here +// There is a compiler bug in MSVC6 which generates incorrect code in this case!! +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // There is an apalling but obscure compiler bug in MSVC6 and earlier: + // vtable_index and 'vtordisp' are always set to 0 in the + // unknown_inheritance case! + // This means that an incorrect function could be called!!! + // Compiling with the /vmg option leads to potentially incorrect code. + // This is probably the reason that the IDE has a user interface for specifying + // the /vmg option, but it is disabled - you can only specify /vmg on + // the command line. In VC1.5 and earlier, the compiler would ICE if it ever + // encountered this situation. + // It is OK to use the /vmg option if /vmm or /vms is specified. + + // Fortunately, the wrong function is only called in very obscure cases. + // It only occurs when a derived class overrides a virtual function declared + // in a virtual base class, and the member function + // points to the *Derived* version of that function. The problem can be + // completely averted in 100% of cases by using the *Base class* for the + // member fpointer. Ie, if you use the base class as an interface, you'll + // stay out of trouble. + // Occasionally, you might want to point directly to a derived class function + // that isn't an override of a base class. In this case, both vtable_index + // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated. + // We can generate correct code in this case. To prevent an incorrect call from + // ever being made, on MSVC6 we generate a warning, and call a function to + // make the program crash instantly. + typedef char ERROR_VC6CompilerBug[-100]; + return 0; + } +}; + + +#else + +// Nasty hack for Microsoft and Intel (IA32 and Itanium) +// unknown_inheritance classes go here +// This is probably the ugliest bit of code I've ever written. Look at the casts! +// There is a compiler bug in MSVC6 which prevents it from using this code. +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // The member function pointer is 16 bytes long. We can't use a normal cast, but + // we can use a union to do the conversion. + union { + XFuncType func; + // In VC++ and ICL, an unknown_inheritance member pointer + // is internally defined as: + struct { + GenericMemFuncType m_funcaddress; // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtordisp; // #bytes to add to 'this' to find the vtable + int vtable_index; // or 0 if no virtual inheritance + } s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + int virtual_delta = 0; + if (u.s.vtable_index) { // Virtual inheritance is used + // First, get to the vtable. + // It is 'vtordisp' bytes from the start of the class. + const int * vtable = *reinterpret_cast( + reinterpret_cast(pthis) + u.s.vtordisp ); + + // 'vtable_index' tells us where in the table we should be looking. + virtual_delta = u.s.vtordisp + *reinterpret_cast( + reinterpret_cast(vtable) + u.s.vtable_index); + } + // The int at 'virtual_delta' gives us the amount to add to 'this'. + // Finally we can add the three components together. Phew! + return reinterpret_cast( + reinterpret_cast(pthis) + u.s.delta + virtual_delta); + }; +}; +#endif // MSVC 7 and greater + +#endif // MS/Intel hacks + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 2: +// +// Define the delegate storage, and cope with static functions +// +//////////////////////////////////////////////////////////////////////////////// + +// DelegateMemento -- an opaque structure which can hold an arbitary delegate. +// It knows nothing about the calling convention or number of arguments used by +// the function pointed to. +// It supplies comparison operators so that it can be stored in STL collections. +// It cannot be set to anything other than null, nor invoked directly: +// it must be converted to a specific delegate. + +// Implementation: +// There are two possible implementations: the Safe method and the Evil method. +// DelegateMemento - Safe version +// +// This implementation is standard-compliant, but a bit tricky. +// A static function pointer is stored inside the class. +// Here are the valid values: +// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+ +// | 0 | 0 | 0 | Empty | +// | !=0 |(dontcare)| Invoker | Static function| +// | 0 | !=0 | !=0* | Method call | +// +--------------------+----------+------------+----------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// When stored stored inside a specific delegate, the 'dontcare' entries are replaced +// with a reference to the delegate itself. This complicates the = and == operators +// for the delegate class. + +// DelegateMemento - Evil version +// +// For compilers where data pointers are at least as big as code pointers, it is +// possible to store the function pointer in the this pointer, using another +// horrible_cast. In this case the DelegateMemento implementation is simple: +// +--pThis --+-- pMemFunc-+-- Meaning---------------------+ +// | 0 | 0 | Empty | +// | !=0 | !=0* | Static function or method call| +// +----------+------------+-------------------------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// Note that the Sun C++ and MSVC documentation explicitly state that they +// support static_cast between void * and function pointers. + +class DelegateMemento { +protected: + // the data is protected, not private, because many + // compilers have problems with template friends. + typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP. + detail::GenericClass *m_pthis; + GenericMemFuncType m_pFunction; + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + typedef void (*GenericFuncPtr)(); // arbitrary code pointer + GenericFuncPtr m_pStaticFunction; +#endif + +public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {}; + void clear() { + m_pthis=0; m_pFunction=0; m_pStaticFunction=0; + } +#else + DelegateMemento() : m_pthis(0), m_pFunction(0) {}; + void clear() { m_pthis=0; m_pFunction=0; } +#endif +public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + inline bool IsEqual (const DelegateMemento &x) const{ + // We have to cope with the static function pointers as a special case + if (m_pFunction!=x.m_pFunction) return false; + // the static function ptrs must either both be equal, or both be 0. + if (m_pStaticFunction!=x.m_pStaticFunction) return false; + if (m_pStaticFunction!=0) return m_pthis==x.m_pthis; + else return true; + } +#else // Evil Method + inline bool IsEqual (const DelegateMemento &x) const{ + return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction; + } +#endif + // Provide a strict weak ordering for DelegateMementos. + inline bool IsLess(const DelegateMemento &right) const { + // deal with static function pointers first +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0) + return m_pStaticFunction < right.m_pStaticFunction; +#endif + if (m_pthis !=right.m_pthis) return m_pthis < right.m_pthis; + // There are no ordering operators for member function pointers, + // but we can fake one by comparing each byte. The resulting ordering is + // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers. + return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0; + + } + // BUGFIX (Mar 2005): + // We can't just compare m_pFunction because on Metrowerks, + // m_pFunction can be zero even if the delegate is not empty! + inline bool operator ! () const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } + inline bool empty() const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } +public: + DelegateMemento & operator = (const DelegateMemento &right) { + SetMementoFrom(right); + return *this; + } + inline bool operator <(const DelegateMemento &right) { + return IsLess(right); + } + inline bool operator >(const DelegateMemento &right) { + return right.IsLess(*this); + } + DelegateMemento (const DelegateMemento &right) : + m_pthis(right.m_pthis), m_pFunction(right.m_pFunction) +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + , m_pStaticFunction (right.m_pStaticFunction) +#endif + {} +protected: + void SetMementoFrom(const DelegateMemento &right) { + m_pFunction = right.m_pFunction; + m_pthis = right.m_pthis; +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = right.m_pStaticFunction; +#endif + } +}; + + +// ClosurePtr<> +// +// A private wrapper class that adds function signatures to DelegateMemento. +// It's the class that does most of the actual work. +// The signatures are specified by: +// GenericMemFunc: must be a type of GenericClass member function pointer. +// StaticFuncPtr: must be a type of function pointer with the same signature +// as GenericMemFunc. +// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6 +// where it never returns void (returns DefaultVoid instead). + +// An outer class, FastDelegateN<>, handles the invoking and creates the +// necessary typedefs. +// This class does everything else. + +namespace detail { + +template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr> +class ClosurePtr : public DelegateMemento { +public: + // These functions are for setting the delegate to a member function. + + // Here's the clever bit: we convert an arbitrary member function into a + // standard form. XMemFunc should be a member function of class X, but I can't + // enforce that here. It needs to be enforced by the wrapper class. + template < class X, class XMemFunc > + inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) { + m_pthis = SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(pthis, function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } + // For const member functions, we only need a const class pointer. + // Since we know that the member function is const, it's safe to + // remove the const qualifier from the 'this' pointer with a const_cast. + // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name. + template < class X, class XMemFunc> + inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) { + m_pthis= SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(const_cast(pthis), function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates + template < class X, class XMemFunc> + inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) { + bindconstmemfunc(pthis, function_to_bind); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#endif + // These functions are required for invoking the stored function + inline GenericClass *GetClosureThis() const { return m_pthis; } + inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast(m_pFunction); } + +// There are a few ways of dealing with static function pointers. +// There's a standard-compliant, but tricky method. +// There's also a straightforward hack, that won't work on DOS compilers using the +// medium memory model. It's so evil that I can't recommend it, but I've +// implemented it anyway because it produces very nice asm code. + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + +// ClosurePtr<> - Safe version +// +// This implementation is standard-compliant, but a bit tricky. +// I store the function pointer inside the class, and the delegate then +// points to itself. Whenever the delegate is copied, these self-references +// must be transformed, and this complicates the = and == operators. +public: + // The next two functions are for operator ==, =, and the copy constructor. + // We may need to convert the m_pthis pointers, so that + // they remain as self-references. + template< class DerivedClass > + inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &x) { + SetMementoFrom(x); + if (m_pStaticFunction!=0) { + // transform self references... + m_pthis=reinterpret_cast(pParent); + } + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + template < class DerivedClass, class ParentInvokerSig > + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind ) { + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + bindmemfunc(pParent, static_function_invoker); + } + m_pStaticFunction=reinterpret_cast(function_to_bind); + } + inline UnvoidStaticFuncPtr GetStaticFunction() const { + return reinterpret_cast(m_pStaticFunction); + } +#else + +// ClosurePtr<> - Evil version +// +// For compilers where data pointers are at least as big as code pointers, it is +// possible to store the function pointer in the this pointer, using another +// horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and +// speeds up comparison and assignment. If C++ provided direct language support +// for delegates, they would produce asm code that was almost identical to this. +// Note that the Sun C++ and MSVC documentation explicitly state that they +// support static_cast between void * and function pointers. + + template< class DerivedClass > + inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &right) { + SetMementoFrom(right); + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + // ******** EVIL, EVIL CODE! ******* + template < class DerivedClass, class ParentInvokerSig> + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind) { + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + // We'll be ignoring the 'this' pointer, but we need to make sure we pass + // a valid value to bindmemfunc(). + bindmemfunc(pParent, static_function_invoker); + } + + // WARNING! Evil hack. We store the function in the 'this' pointer! + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1]; + m_pthis = horrible_cast(function_to_bind); + // MSVC, SunC++ and DMC accept the following (non-standard) code: +// m_pthis = static_cast(static_cast(function_to_bind)); + // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long +// m_pthis = reinterpret_cast(reinterpret_cast(function_to_bind)); + } + // ******** EVIL, EVIL CODE! ******* + // This function will be called with an invalid 'this' pointer!! + // We're just returning the 'this' pointer, converted into + // a function pointer! + inline UnvoidStaticFuncPtr GetStaticFunction() const { + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1]; + return horrible_cast(this); + } +#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + + // Does the closure contain this static function? + inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){ + if (funcptr==0) return empty(); + // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary + // value that is not equal to any valid function pointer. + else return funcptr==reinterpret_cast(GetStaticFunction()); + } +}; + + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 3: +// +// Wrapper classes to ensure type safety +// +//////////////////////////////////////////////////////////////////////////////// + + +// Once we have the member function conversion templates, it's easy to make the +// wrapper classes. So that they will work with as many compilers as possible, +// the classes are of the form +// FastDelegate3 +// They can cope with any combination of parameters. The max number of parameters +// allowed is 8, but it is trivial to increase this limit. +// Note that we need to treat const member functions seperately. +// All this class does is to enforce type safety, and invoke the delegate with +// the correct list of parameters. + +// Because of the weird rule about the class of derived member function pointers, +// you sometimes need to apply a downcast to the 'this' pointer. +// This is the reason for the use of "implicit_cast(pthis)" in the code below. +// If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction, +// without this trick you'd need to write: +// MyDelegate(static_cast(&d), &CDerivedClass::SimpleVirtualFunction); +// but with the trick you can write +// MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction); + +// RetType is the type the compiler uses in compiling the template. For VC6, +// it cannot be void. DesiredRetType is the real type which is returned from +// all of the functions. It can be void. + +// Implicit conversion to "bool" is achieved using the safe_bool idiom, +// using member data pointers (MDP). This allows "if (dg)..." syntax +// Because some compilers (eg codeplay) don't have a unique value for a zero +// MDP, an extra padding member is added to the SafeBool struct. +// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so +// in that case the static function constructor is not made explicit; this +// allows "if (dg==0) ..." to compile. + +//N=0 +template +class FastDelegate0 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(); + typedef RetType (*UnvoidStaticFunctionPtr)(); + typedef RetType (detail::GenericClass::*GenericMemFn)(); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate0 type; + + // Construction and comparison functions + FastDelegate0() { clear(); } + FastDelegate0(const FastDelegate0 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate0 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate0 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate0 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate0 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate0 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate0(Y *pthis, DesiredRetType (X::* function_to_bind)() ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)()) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate0(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate0(DesiredRetType (*function_to_bind)() ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)() ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)()) { + m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() () const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction() const { + return (*(m_Closure.GetStaticFunction()))(); } +}; + +//N=1 +template +class FastDelegate1 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate1 type; + + // Construction and comparison functions + FastDelegate1() { clear(); } + FastDelegate1(const FastDelegate1 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate1 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate1 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate1 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate1 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate1 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate1(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate1(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1)) { + m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1) const { + return (*(m_Closure.GetStaticFunction()))(p1); } +}; + +//N=2 +template +class FastDelegate2 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate2 type; + + // Construction and comparison functions + FastDelegate2() { clear(); } + FastDelegate2(const FastDelegate2 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate2 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate2 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate2 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate2 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate2 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate2(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate2(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2)) { + m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2); } +}; + +//N=3 +template +class FastDelegate3 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate3 type; + + // Construction and comparison functions + FastDelegate3() { clear(); } + FastDelegate3(const FastDelegate3 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate3 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate3 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate3 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate3 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate3 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate3(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate3(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3); } +}; + +//N=4 +template +class FastDelegate4 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate4 type; + + // Construction and comparison functions + FastDelegate4() { clear(); } + FastDelegate4(const FastDelegate4 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate4 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate4 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate4 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate4 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate4 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate4(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate4(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4); } +}; + +//N=5 +template +class FastDelegate5 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate5 type; + + // Construction and comparison functions + FastDelegate5() { clear(); } + FastDelegate5(const FastDelegate5 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate5 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate5 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate5 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate5 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate5 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate5(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate5(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5); } +}; + +//N=6 +template +class FastDelegate6 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate6 type; + + // Construction and comparison functions + FastDelegate6() { clear(); } + FastDelegate6(const FastDelegate6 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate6 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate6 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate6 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate6 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate6 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate6(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate6(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6); } +}; + +//N=7 +template +class FastDelegate7 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate7 type; + + // Construction and comparison functions + FastDelegate7() { clear(); } + FastDelegate7(const FastDelegate7 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate7 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate7 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate7 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate7 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate7 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate7(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate7(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7); } +}; + +//N=8 +template +class FastDelegate8 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate8 type; + + // Construction and comparison functions + FastDelegate8() { clear(); } + FastDelegate8(const FastDelegate8 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate8 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate8 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate8 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate8 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate8 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate8(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate8(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8); } +}; + +//N=9 +template +class FastDelegate9 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate9 type; + + // Construction and comparison functions + FastDelegate9() { clear(); } + FastDelegate9(const FastDelegate9 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate9 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate9 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate9 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate9 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate9 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate9(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate9(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate9(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { + m_Closure.bindstaticfunc(this, &FastDelegate9::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9); } +}; + +//N=10 +template +class FastDelegate10 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate10 type; + + // Construction and comparison functions + FastDelegate10() { clear(); } + FastDelegate10(const FastDelegate10 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate10 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate10 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate10 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate10 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate10 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate10(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate10(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate10(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { + m_Closure.bindstaticfunc(this, &FastDelegate10::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } +}; + +//N=11 +template +class FastDelegate11 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate11 type; + + // Construction and comparison functions + FastDelegate11() { clear(); } + FastDelegate11(const FastDelegate11 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate11 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate11 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate11 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate11 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate11 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate11(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate11(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate11(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + m_Closure.bindstaticfunc(this, &FastDelegate11::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } +}; + +//N=12 +template +class FastDelegate12 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate12 type; + + // Construction and comparison functions + FastDelegate12() { clear(); } + FastDelegate12(const FastDelegate12 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate12 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate12 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate12 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate12 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate12 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate12(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate12(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate12(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + m_Closure.bindstaticfunc(this, &FastDelegate12::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } +}; + +//N=13 +template +class FastDelegate13 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate13 type; + + // Construction and comparison functions + FastDelegate13() { clear(); } + FastDelegate13(const FastDelegate13 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate13 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate13 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate13 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate13 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate13 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate13(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate13(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate13(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + m_Closure.bindstaticfunc(this, &FastDelegate13::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } +}; + +//N=14 +template +class FastDelegate14 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate14 type; + + // Construction and comparison functions + FastDelegate14() { clear(); } + FastDelegate14(const FastDelegate14 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate14 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate14 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate14 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate14 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate14 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate14(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate14(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate14(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { + m_Closure.bindstaticfunc(this, &FastDelegate14::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); } +}; + +//N=15 +template +class FastDelegate15 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate15 type; + + // Construction and comparison functions + FastDelegate15() { clear(); } + FastDelegate15(const FastDelegate15 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate15 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate15 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate15 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate15 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate15 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate15(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate15(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate15(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { + m_Closure.bindstaticfunc(this, &FastDelegate15::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); } +}; + +//N=16 +template +class FastDelegate16 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate16 type; + + // Construction and comparison functions + FastDelegate16() { clear(); } + FastDelegate16(const FastDelegate16 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate16 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate16 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate16 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate16 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate16 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate16(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate16(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate16(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { + m_Closure.bindstaticfunc(this, &FastDelegate16::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16); } +}; + +//N=17 +template +class FastDelegate17 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate17 type; + + // Construction and comparison functions + FastDelegate17() { clear(); } + FastDelegate17(const FastDelegate17 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate17 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate17 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate17 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate17 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate17 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate17(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate17(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate17(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { + m_Closure.bindstaticfunc(this, &FastDelegate17::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17); } +}; + +//N=18 +template +class FastDelegate18 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate18 type; + + // Construction and comparison functions + FastDelegate18() { clear(); } + FastDelegate18(const FastDelegate18 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate18 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate18 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate18 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate18 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate18 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate18(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate18(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate18(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { + m_Closure.bindstaticfunc(this, &FastDelegate18::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18); } +}; + +//N=19 +template +class FastDelegate19 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate19 type; + + // Construction and comparison functions + FastDelegate19() { clear(); } + FastDelegate19(const FastDelegate19 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate19 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate19 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate19 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate19 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate19 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate19(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate19(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate19(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { + m_Closure.bindstaticfunc(this, &FastDelegate19::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19); } +}; + +//N=20 +template +class FastDelegate20 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate20 type; + + // Construction and comparison functions + FastDelegate20() { clear(); } + FastDelegate20(const FastDelegate20 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate20 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate20 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate20 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate20 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate20 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate20(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate20(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate20(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { + m_Closure.bindstaticfunc(this, &FastDelegate20::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20); } +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 4: +// +// FastDelegate<> class (Original author: Jody Hagins) +// Allows boost::function style syntax like: +// FastDelegate< double (int, long) > +// instead of: +// FastDelegate2< int, long, double > +// +//////////////////////////////////////////////////////////////////////////////// + +#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +// Declare FastDelegate as a class template. It will be specialized +// later for all number of arguments. +template +class FastDelegate; + +//N=0 +// Specialization to allow use of +// FastDelegate< R ( ) > +// instead of +// FastDelegate0 < R > +template +class FastDelegate< R ( ) > + // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0 + : public FastDelegate0 < R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate0 < R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=1 +// Specialization to allow use of +// FastDelegate< R ( Param1 ) > +// instead of +// FastDelegate1 < Param1, R > +template +class FastDelegate< R ( Param1 ) > + // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1 + : public FastDelegate1 < Param1, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate1 < Param1, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=2 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2 ) > +// instead of +// FastDelegate2 < Param1, Param2, R > +template +class FastDelegate< R ( Param1, Param2 ) > + // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2 + : public FastDelegate2 < Param1, Param2, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate2 < Param1, Param2, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=3 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3 ) > +// instead of +// FastDelegate3 < Param1, Param2, Param3, R > +template +class FastDelegate< R ( Param1, Param2, Param3 ) > + // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3 + : public FastDelegate3 < Param1, Param2, Param3, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate3 < Param1, Param2, Param3, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=4 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4 ) > +// instead of +// FastDelegate4 < Param1, Param2, Param3, Param4, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4 ) > + // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4 + : public FastDelegate4 < Param1, Param2, Param3, Param4, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate4 < Param1, Param2, Param3, Param4, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=5 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > +// instead of +// FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > + // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5 + : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=6 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > +// instead of +// FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > + // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6 + : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=7 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > +// instead of +// FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > + // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7 + : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=8 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > +// instead of +// FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > + // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8 + : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=9 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9 ) > +// instead of +// FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9 ) > + // Inherit from FastDelegate9 so that it can be treated just like a FastDelegate9 + : public FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=10 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10 ) > +// instead of +// FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10 ) > + // Inherit from FastDelegate10 so that it can be treated just like a FastDelegate10 + : public FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=11 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11 ) > +// instead of +// FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11 ) > + // Inherit from FastDelegate11 so that it can be treated just like a FastDelegate11 + : public FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=12 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12 ) > +// instead of +// FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12 ) > + // Inherit from FastDelegate12 so that it can be treated just like a FastDelegate12 + : public FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=13 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13 ) > +// instead of +// FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13 ) > + // Inherit from FastDelegate13 so that it can be treated just like a FastDelegate13 + : public FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=14 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14 ) > +// instead of +// FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14 ) > + // Inherit from FastDelegate14 so that it can be treated just like a FastDelegate14 + : public FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=15 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15 ) > +// instead of +// FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15 ) > + // Inherit from FastDelegate15 so that it can be treated just like a FastDelegate15 + : public FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=16 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16 ) > +// instead of +// FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16 ) > + // Inherit from FastDelegate16 so that it can be treated just like a FastDelegate16 + : public FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=17 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17 ) > +// instead of +// FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17 ) > + // Inherit from FastDelegate17 so that it can be treated just like a FastDelegate17 + : public FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=18 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18 ) > +// instead of +// FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18 ) > + // Inherit from FastDelegate18 so that it can be treated just like a FastDelegate18 + : public FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=19 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19 ) > +// instead of +// FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19 ) > + // Inherit from FastDelegate19 so that it can be treated just like a FastDelegate19 + : public FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=20 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20 ) > +// instead of +// FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20 ) > + // Inherit from FastDelegate20 so that it can be treated just like a FastDelegate20 + : public FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + + +#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 5: +// +// MakeDelegate() helper function +// +// MakeDelegate(&x, &X::func) returns a fastdelegate of the type +// necessary for calling x.func() with the correct number of arguments. +// This makes it possible to eliminate many typedefs from user code. +// +//////////////////////////////////////////////////////////////////////////////// + +// Also declare overloads of a MakeDelegate() global function to +// reduce the need for typedefs. +// We need seperate overloads for const and non-const member functions. +// Also, because of the weird rule about the class of derived member function pointers, +// implicit downcasts may need to be applied later to the 'this' pointer. +// That's why two classes (X and Y) appear in the definitions. Y must be implicitly +// castable to X. + +// Workaround for VC6. VC6 needs void return types converted into DefaultVoid. +// GCC 3.2 and later won't compile this unless it's preceded by 'typename', +// but VC6 doesn't allow 'typename' in this context. +// So, I have to use a macro. + +#ifdef FASTDLGT_VC6 +#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid::type +#else +#define FASTDLGT_RETTYPE RetType +#endif + +//N=0 +template +FastDelegate0 MakeDelegate(Y* x, RetType (X::*func)()) { + return FastDelegate0(x, func); +} + +template +FastDelegate0 MakeDelegate(Y* x, RetType (X::*func)() const) { + return FastDelegate0(x, func); +} + +template +FastDelegate0 MakeDelegate(RetType (*func)()) { + return FastDelegate0(func); +} + +//N=1 +template +FastDelegate1 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1)) { + return FastDelegate1(x, func); +} + +template +FastDelegate1 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1) const) { + return FastDelegate1(x, func); +} + +template +FastDelegate1 MakeDelegate(RetType (*func)(Param1 p1)) { + return FastDelegate1(func); +} + +//N=2 +template +FastDelegate2 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2)) { + return FastDelegate2(x, func); +} + +template +FastDelegate2 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2) const) { + return FastDelegate2(x, func); +} + +template +FastDelegate2 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2)) { + return FastDelegate2(func); +} + +//N=3 +template +FastDelegate3 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3)) { + return FastDelegate3(x, func); +} + +template +FastDelegate3 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3) const) { + return FastDelegate3(x, func); +} + +template +FastDelegate3 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3)) { + return FastDelegate3(func); +} + +//N=4 +template +FastDelegate4 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + return FastDelegate4(x, func); +} + +template +FastDelegate4 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + return FastDelegate4(x, func); +} + +template +FastDelegate4 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + return FastDelegate4(func); +} + +//N=5 +template +FastDelegate5 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + return FastDelegate5(x, func); +} + +template +FastDelegate5 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + return FastDelegate5(x, func); +} + +template +FastDelegate5 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + return FastDelegate5(func); +} + +//N=6 +template +FastDelegate6 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + return FastDelegate6(x, func); +} + +template +FastDelegate6 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + return FastDelegate6(x, func); +} + +template +FastDelegate6 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + return FastDelegate6(func); +} + +//N=7 +template +FastDelegate7 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + return FastDelegate7(x, func); +} + +template +FastDelegate7 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + return FastDelegate7(x, func); +} + +template +FastDelegate7 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + return FastDelegate7(func); +} + +//N=8 +template +FastDelegate8 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + return FastDelegate8(x, func); +} + +template +FastDelegate8 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + return FastDelegate8(x, func); +} + +template +FastDelegate8 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + return FastDelegate8(func); +} + +//N=9 +template +FastDelegate9 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { + return FastDelegate9(x, func); +} + +template +FastDelegate9 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const) { + return FastDelegate9(x, func); +} + +template +FastDelegate9 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { + return FastDelegate9(func); +} + +//N=10 +template +FastDelegate10 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { + return FastDelegate10(x, func); +} + +template +FastDelegate10 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const) { + return FastDelegate10(x, func); +} + +template +FastDelegate10 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { + return FastDelegate10(func); +} + +//N=11 +template +FastDelegate11 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + return FastDelegate11(x, func); +} + +template +FastDelegate11 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { + return FastDelegate11(x, func); +} + +template +FastDelegate11 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + return FastDelegate11(func); +} + +//N=12 +template +FastDelegate12 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + return FastDelegate12(x, func); +} + +template +FastDelegate12 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { + return FastDelegate12(x, func); +} + +template +FastDelegate12 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + return FastDelegate12(func); +} + +//N=13 +template +FastDelegate13 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + return FastDelegate13(x, func); +} + +template +FastDelegate13 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { + return FastDelegate13(x, func); +} + +template +FastDelegate13 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + return FastDelegate13(func); +} + +//N=14 +template +FastDelegate14 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { + return FastDelegate14(x, func); +} + +template +FastDelegate14 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const) { + return FastDelegate14(x, func); +} + +template +FastDelegate14 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { + return FastDelegate14(func); +} + +//N=15 +template +FastDelegate15 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { + return FastDelegate15(x, func); +} + +template +FastDelegate15 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const) { + return FastDelegate15(x, func); +} + +template +FastDelegate15 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { + return FastDelegate15(func); +} + +//N=16 +template +FastDelegate16 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { + return FastDelegate16(x, func); +} + +template +FastDelegate16 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const) { + return FastDelegate16(x, func); +} + +template +FastDelegate16 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { + return FastDelegate16(func); +} + +//N=17 +template +FastDelegate17 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { + return FastDelegate17(x, func); +} + +template +FastDelegate17 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const) { + return FastDelegate17(x, func); +} + +template +FastDelegate17 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { + return FastDelegate17(func); +} + +//N=18 +template +FastDelegate18 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { + return FastDelegate18(x, func); +} + +template +FastDelegate18 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const) { + return FastDelegate18(x, func); +} + +template +FastDelegate18 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { + return FastDelegate18(func); +} + +//N=19 +template +FastDelegate19 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { + return FastDelegate19(x, func); +} + +template +FastDelegate19 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const) { + return FastDelegate19(x, func); +} + +template +FastDelegate19 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { + return FastDelegate19(func); +} + +//N=20 +template +FastDelegate20 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { + return FastDelegate20(x, func); +} + +template +FastDelegate20 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const) { + return FastDelegate20(x, func); +} + +template +FastDelegate20 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { + return FastDelegate20(func); +} + + + // clean up after ourselves... +#undef FASTDLGT_RETTYPE + +} // namespace fastdelegate + +#endif // !defined(FASTDELEGATE_H) diff --git a/utils/mmsource/core-legacy/sourcehook/generate/FastDelegate.hxx b/utils/mmsource/core-legacy/sourcehook/generate/FastDelegate.hxx new file mode 100644 index 00000000..6f2fe49c --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/FastDelegate.hxx @@ -0,0 +1,1054 @@ +// FastDelegate.h +// Efficient delegates in C++ that generate only two lines of asm code! +// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp +// +// - Don Clugston, Mar 2004. +// Major contributions were made by Jody Hagins. +// History: +// 24-Apr-04 1.0 * Submitted to CodeProject. +// 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack. +// * Improved syntax for horrible_cast (thanks Paul Bludov). +// * Tested on Metrowerks MWCC and Intel ICL (IA32) +// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL. +// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5 +// * Now works on /clr "managed C++" code on VC7, VC7.1 +// * Comeau C++ now compiles without warnings. +// * Prevent the virtual inheritance case from being used on +// VC6 and earlier, which generate incorrect code. +// * Improved warning and error messages. Non-standard hacks +// now have compile-time checks to make them safer. +// * implicit_cast used instead of static_cast in many cases. +// * If calling a const member function, a const class pointer can be used. +// * MakeDelegate() global helper function added to simplify pass-by-value. +// * Added fastdelegate.clear() +// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates) +// 30-Oct-04 1.3 * Support for (non-void) return values. +// * No more workarounds in client code! +// MSVC and Intel now use a clever hack invented by John Dlugosz: +// - The FASTDELEGATEDECLARE workaround is no longer necessary. +// - No more warning messages for VC6 +// * Less use of macros. Error messages should be more comprehensible. +// * Added include guards +// * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks). +// * Now tested on VS 2005 Express Beta, PGI C++ +// 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates. +// * <,>,<=,>= comparison operators to allow storage in ordered containers. +// * Substantial reduction of code size, especially the 'Closure' class. +// * Standardised all the compiler-specific workarounds. +// * MFP conversion now works for CodePlay (but not yet supported in the full code). +// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1 +// * New syntax: FastDelegate< int (char *, double) >. +// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric). +// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium. +// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())" +// * Fully supported by CodePlay VectorC +// * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC! +// * More optimal assignment,== and != operators for static function pointers. + +#ifndef FASTDELEGATE_H +#define FASTDELEGATE_H + +#ifdef _MSC_VER +# if _MSC_VER > 1000 +# pragma once +# endif // _MSC_VER > 1000 +#endif // #ifdef _MSC_VER + +#include // to allow <,> comparisons + +//////////////////////////////////////////////////////////////////////////////// +// Configuration options +// +//////////////////////////////////////////////////////////////////////////////// + +// Uncomment the following #define for optimally-sized delegates. +// In this case, the generated asm code is almost identical to the code you'd get +// if the compiler had native support for delegates. +// It will not work on systems where sizeof(dataptr) < sizeof(codeptr). +// Thus, it will not work for DOS compilers using the medium model. +// It will also probably fail on some DSP systems. +#define FASTDELEGATE_USESTATICFUNCTIONHACK + +// Uncomment the next line to allow function declarator syntax. +// It is automatically enabled for those compilers where it is known to work. +//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Compiler identification for workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Compiler identification. It's not easy to identify Visual C++ because +// many vendors fraudulently define Microsoft's identifiers. +#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__) +#define FASTDLGT_ISMSVC + +#if (_MSC_VER <1300) // Many workarounds are required for VC6. +#define FASTDLGT_VC6 +#pragma warning(disable:4786) // disable this ridiculous warning +#endif + +#endif + +// Does the compiler uses Microsoft's member function pointer structure? +// If so, it needs special treatment. +// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's +// identifier, _MSC_VER. We need to filter Metrowerks out. +#if defined(_MSC_VER) && !defined(__MWERKS__) +#define FASTDLGT_MICROSOFT_MFP + +#if !defined(__VECTOR_C) +// CodePlay doesn't have the __single/multi/virtual_inheritance keywords +#define FASTDLGT_HASINHERITANCE_KEYWORDS +#endif +#endif + +// Does it allow function declarator syntax? The following compilers are known to work: +#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1 +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use. +#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too. +#if defined (__MWERKS__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +#ifdef __GNUC__ // Workaround GCC bug #8271 + // At present, GCC doesn't recognize constness of MFPs in templates +#define FASTDELEGATE_GCC_BUG_8271 +#endif + + + +//////////////////////////////////////////////////////////////////////////////// +// General tricks used in this code +// +// (a) Error messages are generated by typdefing an array of negative size to +// generate compile-time errors. +// (b) Warning messages on MSVC are generated by declaring unused variables, and +// enabling the "variable XXX is never used" warning. +// (c) Unions are used in a few compiler-specific cases to perform illegal casts. +// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to +// (char *) first to ensure that the correct number of *bytes* are added. +// +//////////////////////////////////////////////////////////////////////////////// +// Helper templates +// +//////////////////////////////////////////////////////////////////////////////// + + +namespace fastdelegate { +namespace detail { // we'll hide the implementation details in a nested namespace. + +// implicit_cast< > +// I believe this was originally going to be in the C++ standard but +// was left out by accident. It's even milder than static_cast. +// I use it instead of static_cast<> to emphasize that I'm not doing +// anything nasty. +// Usage is identical to static_cast<> +template +inline OutputClass implicit_cast(InputClass input){ + return input; +} + +// horrible_cast< > +// This is truly evil. It completely subverts C++'s type system, allowing you +// to cast from any class to any other class. Technically, using a union +// to perform the cast is undefined behaviour (even in C). But we can see if +// it is OK by checking that the union is the same size as each of its members. +// horrible_cast<> should only be used for compiler-specific workarounds. +// Usage is identical to reinterpret_cast<>. + +// This union is declared outside the horrible_cast because BCC 5.5.1 +// can't inline a function with a nested class, and gives a warning. +template +union horrible_union{ + OutputClass out; + InputClass in; +}; + +template +inline OutputClass horrible_cast(const InputClass input){ + horrible_union u; + // Cause a compile-time error if in, out and u are not the same size. + // If the compile fails here, it means the compiler has peculiar + // unions which would prevent the cast from working. + typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) + && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1]; + u.in = input; + return u.out; +} + +//////////////////////////////////////////////////////////////////////////////// +// Workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Backwards compatibility: This macro used to be necessary in the virtual inheritance +// case for Intel and Microsoft. Now it just forward-declares the class. +#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME; + +// Prevent use of the static function hack with the DOS medium model. +#ifdef __MEDIUM__ +#undef FASTDELEGATE_USESTATICFUNCTIONHACK +#endif + +// DefaultVoid - a workaround for 'void' templates in VC6. +// +// (1) VC6 and earlier do not allow 'void' as a default template argument. +// (2) They also doesn't allow you to return 'void' from a function. +// +// Workaround for (1): Declare a dummy type 'DefaultVoid' which we use +// when we'd like to use 'void'. We convert it into 'void' and back +// using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>. +// Workaround for (2): On VC6, the code for calling a void function is +// identical to the code for calling a non-void function in which the +// return value is never used, provided the return value is returned +// in the EAX register, rather than on the stack. +// This is true for most fundamental types such as int, enum, void *. +// Const void * is the safest option since it doesn't participate +// in any automatic conversions. But on a 16-bit compiler it might +// cause extra code to be generated, so we disable it for all compilers +// except for VC6 (and VC5). +#ifdef FASTDLGT_VC6 +// VC6 workaround +typedef const void * DefaultVoid; +#else +// On any other compiler, just use a normal void. +typedef void DefaultVoid; +#endif + +// Translate from 'DefaultVoid' to 'void'. +// Everything else is unchanged +template +struct DefaultVoidToVoid { typedef T type; }; + +template <> +struct DefaultVoidToVoid { typedef void type; }; + +// Translate from 'void' into 'DefaultVoid' +// Everything else is unchanged +template +struct VoidToDefaultVoid { typedef T type; }; + +template <> +struct VoidToDefaultVoid { typedef DefaultVoid type; }; + + + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 1: +// +// Conversion of member function pointer to a standard form +// +//////////////////////////////////////////////////////////////////////////////// + +// GenericClass is a fake class, ONLY used to provide a type. +// It is vitally important that it is never defined, so that the compiler doesn't +// think it can optimize the invocation. For example, Borland generates simpler +// code if it knows the class only uses single inheritance. + +// Compilers using Microsoft's structure need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS + // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP + // (4 bytes), even when the /vmg option is used. Declaring an empty class + // would give 16 byte pointers in this case.... + class __single_inheritance GenericClass; +#endif + // ...but for Codeplay, an empty class *always* gives 4 byte pointers. + // If compiled with the /clr option ("managed C++"), the JIT compiler thinks + // it needs to load GenericClass before it can call any of its functions, + // (compiles OK but crashes at runtime!), so we need to declare an + // empty class to make it happy. + // Codeplay and VC4 can't cope with the unknown_inheritance case either. + class GenericClass {}; +#else + class GenericClass; +#endif + +// The size of a single inheritance member function pointer. +const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)()); + +// SimplifyMemFunc< >::Convert() +// +// A template function that converts an arbitrary member function pointer into the +// simplest possible form of member function pointer, using a supplied 'this' pointer. +// According to the standard, this can be done legally with reinterpret_cast<>. +// For (non-standard) compilers which use member function pointers which vary in size +// depending on the class, we need to use knowledge of the internal structure of a +// member function pointer, as used by the compiler. Template specialization is used +// to distinguish between the sizes. Because some compilers don't support partial +// template specialisation, I use full specialisation of a wrapper struct. + +// general case -- don't know how to convert it. Force a compile failure +template +struct SimplifyMemFunc { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // Unsupported member function type -- force a compile failure. + // (it's illegal to have a array with negative size). + typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100]; + return 0; + } +}; + +// For compilers where all member func ptrs are the same size, everything goes here. +// For non-standard compilers, only single_inheritance classes go here. +template <> +struct SimplifyMemFunc { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { +#if defined __DMC__ + // Digital Mars doesn't allow you to cast between abitrary PMF's, + // even though the standard says you can. The 32-bit compiler lets you + // static_cast through an int, but the DOS compiler doesn't. + bound_func = horrible_cast(function_to_bind); +#else + bound_func = reinterpret_cast(function_to_bind); +#endif + return reinterpret_cast(pthis); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 1b: +// +// Workarounds for Microsoft and Intel +// +//////////////////////////////////////////////////////////////////////////////// + + +// Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay), +// need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +// We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1) +// at the start of each function for extra safety, but VC6 seems to ICE +// intermittently if you do this inside a template. + +// __multiple_inheritance classes go here +// Nasty hack for Microsoft and Intel (IA32 and Itanium) +template<> +struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) > { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // We need to use a horrible_cast to do this conversion. + // In MSVC, a multiple inheritance member pointer is internally defined as: + union { + XFuncType func; + struct { + GenericMemFuncType funcaddress; // points to the actual member function + int delta; // #BYTES to be added to the 'this' pointer + }s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + return reinterpret_cast(reinterpret_cast(pthis) + u.s.delta); + } +}; + +// virtual inheritance is a real nuisance. It's inefficient and complicated. +// On MSVC and Intel, there isn't enough information in the pointer itself to +// enable conversion to a closure pointer. Earlier versions of this code didn't +// work for all cases, and generated a compile-time error instead. +// But a very clever hack invented by John M. Dlugosz solves this problem. +// My code is somewhat different to his: I have no asm code, and I make no +// assumptions about the calling convention that is used. + +// In VC++ and ICL, a virtual_inheritance member pointer +// is internally defined as: +struct MicrosoftVirtualMFP { + void (GenericClass::*codeptr)(); // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtable_index; // or 0 if no virtual inheritance +}; +// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the +// m_codeptr member is *always* called, regardless of the values of the other +// members. (This is *not* true for other compilers, eg GCC, which obtain the +// function address from the vtable if a virtual function is being called). +// Dlugosz's trick is to make the codeptr point to a probe function which +// returns the 'this' pointer that was used. + +// Define a generic class that uses virtual inheritance. +// It has a trival member function that returns the value of the 'this' pointer. +struct GenericVirtualClass : virtual public GenericClass +{ + typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); + GenericVirtualClass * GetThis() { return this; } +}; + +// __virtual_inheritance classes go here +template <> +struct SimplifyMemFunc +{ + + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + union { + XFuncType func; + GenericClass* (X::*ProbeFunc)(); + MicrosoftVirtualMFP s; + } u; + u.func = function_to_bind; + bound_func = reinterpret_cast(u.s.codeptr); + union { + GenericVirtualClass::ProbePtrType virtfunc; + MicrosoftVirtualMFP s; + } u2; + // Check that the horrible_cast<>s will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s) + && sizeof(function_to_bind)==sizeof(u.ProbeFunc) + && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; + // Unfortunately, taking the address of a MF prevents it from being inlined, so + // this next line can't be completely optimised away by the compiler. + u2.virtfunc = &GenericVirtualClass::GetThis; + u.s.codeptr = u2.s.codeptr; + return (pthis->*u.ProbeFunc)(); + } +}; + +#if (_MSC_VER <1300) + +// Nasty hack for Microsoft Visual C++ 6.0 +// unknown_inheritance classes go here +// There is a compiler bug in MSVC6 which generates incorrect code in this case!! +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // There is an apalling but obscure compiler bug in MSVC6 and earlier: + // vtable_index and 'vtordisp' are always set to 0 in the + // unknown_inheritance case! + // This means that an incorrect function could be called!!! + // Compiling with the /vmg option leads to potentially incorrect code. + // This is probably the reason that the IDE has a user interface for specifying + // the /vmg option, but it is disabled - you can only specify /vmg on + // the command line. In VC1.5 and earlier, the compiler would ICE if it ever + // encountered this situation. + // It is OK to use the /vmg option if /vmm or /vms is specified. + + // Fortunately, the wrong function is only called in very obscure cases. + // It only occurs when a derived class overrides a virtual function declared + // in a virtual base class, and the member function + // points to the *Derived* version of that function. The problem can be + // completely averted in 100% of cases by using the *Base class* for the + // member fpointer. Ie, if you use the base class as an interface, you'll + // stay out of trouble. + // Occasionally, you might want to point directly to a derived class function + // that isn't an override of a base class. In this case, both vtable_index + // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated. + // We can generate correct code in this case. To prevent an incorrect call from + // ever being made, on MSVC6 we generate a warning, and call a function to + // make the program crash instantly. + typedef char ERROR_VC6CompilerBug[-100]; + return 0; + } +}; + + +#else + +// Nasty hack for Microsoft and Intel (IA32 and Itanium) +// unknown_inheritance classes go here +// This is probably the ugliest bit of code I've ever written. Look at the casts! +// There is a compiler bug in MSVC6 which prevents it from using this code. +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // The member function pointer is 16 bytes long. We can't use a normal cast, but + // we can use a union to do the conversion. + union { + XFuncType func; + // In VC++ and ICL, an unknown_inheritance member pointer + // is internally defined as: + struct { + GenericMemFuncType m_funcaddress; // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtordisp; // #bytes to add to 'this' to find the vtable + int vtable_index; // or 0 if no virtual inheritance + } s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + int virtual_delta = 0; + if (u.s.vtable_index) { // Virtual inheritance is used + // First, get to the vtable. + // It is 'vtordisp' bytes from the start of the class. + const int * vtable = *reinterpret_cast( + reinterpret_cast(pthis) + u.s.vtordisp ); + + // 'vtable_index' tells us where in the table we should be looking. + virtual_delta = u.s.vtordisp + *reinterpret_cast( + reinterpret_cast(vtable) + u.s.vtable_index); + } + // The int at 'virtual_delta' gives us the amount to add to 'this'. + // Finally we can add the three components together. Phew! + return reinterpret_cast( + reinterpret_cast(pthis) + u.s.delta + virtual_delta); + }; +}; +#endif // MSVC 7 and greater + +#endif // MS/Intel hacks + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 2: +// +// Define the delegate storage, and cope with static functions +// +//////////////////////////////////////////////////////////////////////////////// + +// DelegateMemento -- an opaque structure which can hold an arbitary delegate. +// It knows nothing about the calling convention or number of arguments used by +// the function pointed to. +// It supplies comparison operators so that it can be stored in STL collections. +// It cannot be set to anything other than null, nor invoked directly: +// it must be converted to a specific delegate. + +// Implementation: +// There are two possible implementations: the Safe method and the Evil method. +// DelegateMemento - Safe version +// +// This implementation is standard-compliant, but a bit tricky. +// A static function pointer is stored inside the class. +// Here are the valid values: +// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+ +// | 0 | 0 | 0 | Empty | +// | !=0 |(dontcare)| Invoker | Static function| +// | 0 | !=0 | !=0* | Method call | +// +--------------------+----------+------------+----------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// When stored stored inside a specific delegate, the 'dontcare' entries are replaced +// with a reference to the delegate itself. This complicates the = and == operators +// for the delegate class. + +// DelegateMemento - Evil version +// +// For compilers where data pointers are at least as big as code pointers, it is +// possible to store the function pointer in the this pointer, using another +// horrible_cast. In this case the DelegateMemento implementation is simple: +// +--pThis --+-- pMemFunc-+-- Meaning---------------------+ +// | 0 | 0 | Empty | +// | !=0 | !=0* | Static function or method call| +// +----------+------------+-------------------------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// Note that the Sun C++ and MSVC documentation explicitly state that they +// support static_cast between void * and function pointers. + +class DelegateMemento { +protected: + // the data is protected, not private, because many + // compilers have problems with template friends. + typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP. + detail::GenericClass *m_pthis; + GenericMemFuncType m_pFunction; + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + typedef void (*GenericFuncPtr)(); // arbitrary code pointer + GenericFuncPtr m_pStaticFunction; +#endif + +public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {}; + void clear() { + m_pthis=0; m_pFunction=0; m_pStaticFunction=0; + } +#else + DelegateMemento() : m_pthis(0), m_pFunction(0) {}; + void clear() { m_pthis=0; m_pFunction=0; } +#endif +public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + inline bool IsEqual (const DelegateMemento &x) const{ + // We have to cope with the static function pointers as a special case + if (m_pFunction!=x.m_pFunction) return false; + // the static function ptrs must either both be equal, or both be 0. + if (m_pStaticFunction!=x.m_pStaticFunction) return false; + if (m_pStaticFunction!=0) return m_pthis==x.m_pthis; + else return true; + } +#else // Evil Method + inline bool IsEqual (const DelegateMemento &x) const{ + return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction; + } +#endif + // Provide a strict weak ordering for DelegateMementos. + inline bool IsLess(const DelegateMemento &right) const { + // deal with static function pointers first +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0) + return m_pStaticFunction < right.m_pStaticFunction; +#endif + if (m_pthis !=right.m_pthis) return m_pthis < right.m_pthis; + // There are no ordering operators for member function pointers, + // but we can fake one by comparing each byte. The resulting ordering is + // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers. + return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0; + + } + // BUGFIX (Mar 2005): + // We can't just compare m_pFunction because on Metrowerks, + // m_pFunction can be zero even if the delegate is not empty! + inline bool operator ! () const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } + inline bool empty() const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } +public: + DelegateMemento & operator = (const DelegateMemento &right) { + SetMementoFrom(right); + return *this; + } + inline bool operator <(const DelegateMemento &right) { + return IsLess(right); + } + inline bool operator >(const DelegateMemento &right) { + return right.IsLess(*this); + } + DelegateMemento (const DelegateMemento &right) : + m_pthis(right.m_pthis), m_pFunction(right.m_pFunction) +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + , m_pStaticFunction (right.m_pStaticFunction) +#endif + {} +protected: + void SetMementoFrom(const DelegateMemento &right) { + m_pFunction = right.m_pFunction; + m_pthis = right.m_pthis; +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = right.m_pStaticFunction; +#endif + } +}; + + +// ClosurePtr<> +// +// A private wrapper class that adds function signatures to DelegateMemento. +// It's the class that does most of the actual work. +// The signatures are specified by: +// GenericMemFunc: must be a type of GenericClass member function pointer. +// StaticFuncPtr: must be a type of function pointer with the same signature +// as GenericMemFunc. +// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6 +// where it never returns void (returns DefaultVoid instead). + +// An outer class, FastDelegateN<>, handles the invoking and creates the +// necessary typedefs. +// This class does everything else. + +namespace detail { + +template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr> +class ClosurePtr : public DelegateMemento { +public: + // These functions are for setting the delegate to a member function. + + // Here's the clever bit: we convert an arbitrary member function into a + // standard form. XMemFunc should be a member function of class X, but I can't + // enforce that here. It needs to be enforced by the wrapper class. + template < class X, class XMemFunc > + inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) { + m_pthis = SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(pthis, function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } + // For const member functions, we only need a const class pointer. + // Since we know that the member function is const, it's safe to + // remove the const qualifier from the 'this' pointer with a const_cast. + // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name. + template < class X, class XMemFunc> + inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) { + m_pthis= SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(const_cast(pthis), function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates + template < class X, class XMemFunc> + inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) { + bindconstmemfunc(pthis, function_to_bind); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#endif + // These functions are required for invoking the stored function + inline GenericClass *GetClosureThis() const { return m_pthis; } + inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast(m_pFunction); } + +// There are a few ways of dealing with static function pointers. +// There's a standard-compliant, but tricky method. +// There's also a straightforward hack, that won't work on DOS compilers using the +// medium memory model. It's so evil that I can't recommend it, but I've +// implemented it anyway because it produces very nice asm code. + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + +// ClosurePtr<> - Safe version +// +// This implementation is standard-compliant, but a bit tricky. +// I store the function pointer inside the class, and the delegate then +// points to itself. Whenever the delegate is copied, these self-references +// must be transformed, and this complicates the = and == operators. +public: + // The next two functions are for operator ==, =, and the copy constructor. + // We may need to convert the m_pthis pointers, so that + // they remain as self-references. + template< class DerivedClass > + inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &x) { + SetMementoFrom(x); + if (m_pStaticFunction!=0) { + // transform self references... + m_pthis=reinterpret_cast(pParent); + } + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + template < class DerivedClass, class ParentInvokerSig > + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind ) { + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + bindmemfunc(pParent, static_function_invoker); + } + m_pStaticFunction=reinterpret_cast(function_to_bind); + } + inline UnvoidStaticFuncPtr GetStaticFunction() const { + return reinterpret_cast(m_pStaticFunction); + } +#else + +// ClosurePtr<> - Evil version +// +// For compilers where data pointers are at least as big as code pointers, it is +// possible to store the function pointer in the this pointer, using another +// horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and +// speeds up comparison and assignment. If C++ provided direct language support +// for delegates, they would produce asm code that was almost identical to this. +// Note that the Sun C++ and MSVC documentation explicitly state that they +// support static_cast between void * and function pointers. + + template< class DerivedClass > + inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &right) { + SetMementoFrom(right); + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + // ******** EVIL, EVIL CODE! ******* + template < class DerivedClass, class ParentInvokerSig> + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind) { + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + // We'll be ignoring the 'this' pointer, but we need to make sure we pass + // a valid value to bindmemfunc(). + bindmemfunc(pParent, static_function_invoker); + } + + // WARNING! Evil hack. We store the function in the 'this' pointer! + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1]; + m_pthis = horrible_cast(function_to_bind); + // MSVC, SunC++ and DMC accept the following (non-standard) code: +// m_pthis = static_cast(static_cast(function_to_bind)); + // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long +// m_pthis = reinterpret_cast(reinterpret_cast(function_to_bind)); + } + // ******** EVIL, EVIL CODE! ******* + // This function will be called with an invalid 'this' pointer!! + // We're just returning the 'this' pointer, converted into + // a function pointer! + inline UnvoidStaticFuncPtr GetStaticFunction() const { + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1]; + return horrible_cast(this); + } +#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + + // Does the closure contain this static function? + inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){ + if (funcptr==0) return empty(); + // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary + // value that is not equal to any valid function pointer. + else return funcptr==reinterpret_cast(GetStaticFunction()); + } +}; + + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 3: +// +// Wrapper classes to ensure type safety +// +//////////////////////////////////////////////////////////////////////////////// + + +// Once we have the member function conversion templates, it's easy to make the +// wrapper classes. So that they will work with as many compilers as possible, +// the classes are of the form +// FastDelegate3 +// They can cope with any combination of parameters. The max number of parameters +// allowed is 8, but it is trivial to increase this limit. +// Note that we need to treat const member functions seperately. +// All this class does is to enforce type safety, and invoke the delegate with +// the correct list of parameters. + +// Because of the weird rule about the class of derived member function pointers, +// you sometimes need to apply a downcast to the 'this' pointer. +// This is the reason for the use of "implicit_cast(pthis)" in the code below. +// If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction, +// without this trick you'd need to write: +// MyDelegate(static_cast(&d), &CDerivedClass::SimpleVirtualFunction); +// but with the trick you can write +// MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction); + +// RetType is the type the compiler uses in compiling the template. For VC6, +// it cannot be void. DesiredRetType is the real type which is returned from +// all of the functions. It can be void. + +// Implicit conversion to "bool" is achieved using the safe_bool idiom, +// using member data pointers (MDP). This allows "if (dg)..." syntax +// Because some compilers (eg codeplay) don't have a unique value for a zero +// MDP, an extra padding member is added to the SafeBool struct. +// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so +// in that case the static function constructor is not made explicit; this +// allows "if (dg==0) ..." to compile. + +@VARARGS +template<@CLASSARGS, class RetType=detail::DefaultVoid> +class FastDelegate@NUM { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(@FUNCARGS); + typedef RetType (*UnvoidStaticFunctionPtr)(@FUNCARGS); + typedef RetType (detail::GenericClass::*GenericMemFn)(@FUNCARGS); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate@NUM type; + + // Construction and comparison functions + FastDelegate@NUM() { clear(); } + FastDelegate@NUM(const FastDelegate@NUM &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate@NUM &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate@NUM &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate@NUM &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate@NUM &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate@NUM &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate@NUM(Y *pthis, DesiredRetType (X::* function_to_bind)(@FUNCARGS) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(@FUNCARGS)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate@NUM(const Y *pthis, DesiredRetType (X::* function_to_bind)(@FUNCARGS) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(@FUNCARGS) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate@NUM(DesiredRetType (*function_to_bind)(@FUNCARGS) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(@FUNCARGS) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(@FUNCARGS)) { + m_Closure.bindstaticfunc(this, &FastDelegate@NUM::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (@FUNCARGS) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(@INVOKEARGS); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(@FUNCARGS) const { + return (*(m_Closure.GetStaticFunction()))(@INVOKEARGS); } +}; + +@ENDVAR + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 4: +// +// FastDelegate<> class (Original author: Jody Hagins) +// Allows boost::function style syntax like: +// FastDelegate< double (int, long) > +// instead of: +// FastDelegate2< int, long, double > +// +//////////////////////////////////////////////////////////////////////////////// + +#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +// Declare FastDelegate as a class template. It will be specialized +// later for all number of arguments. +template +class FastDelegate; + +@VARARGS +// Specialization to allow use of +// FastDelegate< R ( @SELARGS ) > +// instead of +// FastDelegate@NUM < @SELARGS, R > +template +class FastDelegate< R ( @SELARGS ) > + // Inherit from FastDelegate@NUM so that it can be treated just like a FastDelegate@NUM + : public FastDelegate@NUM < @SELARGS, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate@NUM < @SELARGS, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( @FUNCARGS )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( @FUNCARGS ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( @FUNCARGS )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +@ENDVAR + +#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 5: +// +// MakeDelegate() helper function +// +// MakeDelegate(&x, &X::func) returns a fastdelegate of the type +// necessary for calling x.func() with the correct number of arguments. +// This makes it possible to eliminate many typedefs from user code. +// +//////////////////////////////////////////////////////////////////////////////// + +// Also declare overloads of a MakeDelegate() global function to +// reduce the need for typedefs. +// We need seperate overloads for const and non-const member functions. +// Also, because of the weird rule about the class of derived member function pointers, +// implicit downcasts may need to be applied later to the 'this' pointer. +// That's why two classes (X and Y) appear in the definitions. Y must be implicitly +// castable to X. + +// Workaround for VC6. VC6 needs void return types converted into DefaultVoid. +// GCC 3.2 and later won't compile this unless it's preceded by 'typename', +// but VC6 doesn't allow 'typename' in this context. +// So, I have to use a macro. + +#ifdef FASTDLGT_VC6 +#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid::type +#else +#define FASTDLGT_RETTYPE RetType +#endif + +@VARARGS +template +FastDelegate@NUM<@SELARGS, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(@FUNCARGS)) { + return FastDelegate@NUM<@SELARGS, FASTDLGT_RETTYPE>(x, func); +} + +template +FastDelegate@NUM<@SELARGS, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(@FUNCARGS) const) { + return FastDelegate@NUM<@SELARGS, FASTDLGT_RETTYPE>(x, func); +} + +template <@CLASSARGS, class RetType> +FastDelegate@NUM<@SELARGS, FASTDLGT_RETTYPE> MakeDelegate(RetType (*func)(@FUNCARGS)) { + return FastDelegate@NUM<@SELARGS, FASTDLGT_RETTYPE>(func); +} + +@ENDVAR + + // clean up after ourselves... +#undef FASTDLGT_RETTYPE + +} // namespace fastdelegate + +#endif // !defined(FASTDELEGATE_H) diff --git a/utils/mmsource/core-legacy/sourcehook/generate/generate b/utils/mmsource/core-legacy/sourcehook/generate/generate new file mode 100644 index 00000000..f537ff3b --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/generate @@ -0,0 +1,7 @@ +#/bin/sh + +./shworker.bin iter sourcehook.hxx sourcehook.h $1 +./shworker.bin iter sh_memfuncinfo.hxx sh_memfuncinfo.h $1 +./shworker.bin hopter FastDelegate.hxx FastDelegate.h $1 + +cp *.h .. diff --git a/utils/mmsource/core-legacy/sourcehook/generate/generate.bat b/utils/mmsource/core-legacy/sourcehook/generate/generate.bat new file mode 100644 index 00000000..53c863ae --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/generate.bat @@ -0,0 +1,10 @@ +:: Generates everything +:: Usage: +:: generate.bat + + +shworker iter sourcehook.hxx sourcehook.h %1 +shworker iter sh_memfuncinfo.hxx sh_memfuncinfo.h %1 +shworker hopter FastDelegate.hxx FastDelegate.h %1 + +copy *.h .. \ No newline at end of file diff --git a/utils/mmsource/core-legacy/sourcehook/generate/sh_memfuncinfo.h b/utils/mmsource/core-legacy/sourcehook/generate/sh_memfuncinfo.h new file mode 100644 index 00000000..fbfddab9 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/sh_memfuncinfo.h @@ -0,0 +1,912 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2007 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +/** + * @brief This file provides a way for getting information about a member function. + * @file sh_memfuncinfo.h + */ + +#ifndef __SHINT_MEMFUNC_INFO_H__ +#define __SHINT_MEMFUNC_INFO_H__ + +namespace SourceHook +{ + + // Don Clugston: + // implicit_cast< > + // I believe this was originally going to be in the C++ standard but + // was left out by accident. It's even milder than static_cast. + // I use it instead of static_cast<> to emphasize that I'm not doing + // anything nasty. + // Usage is identical to static_cast<> + template + inline OutputClass implicit_cast(InputClass input){ + return input; + } + + + struct MemFuncInfo + { + bool isVirtual; // Is the function virtual? + int thisptroffs; // The this pointer the function expects to be called with + // If -1, you need to call the GetFuncInfo_GetThisPtr function + int vtblindex; // The function's index in the vtable (0-based, 1=second entry, 2=third entry, ...) + int vtbloffs; // The vtable pointer + }; + + // Ideas by Don Clugston. + // Check out his excellent paper: http://www.codeproject.com/cpp/FastDelegate.asp + + template struct MFI_Impl + { + template static inline void GetFuncInfo(MFP *mfp, MemFuncInfo &out) + { + static char weird_memfunc_pointer_exclamation_mark_arrow_error[N-1000]; + } + }; + +# if SH_COMP == SH_COMP_GCC + + template<> struct MFI_Impl<2*SH_PTRSIZE> // All of these have size==8/16 + { + struct GCC_MemFunPtr + { + union + { + void *funcadr; // always even + intptr_t vtable_index_plus1; // = vindex+1, always odd + }; + intptr_t delta; + }; + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + GCC_MemFunPtr *mfp_detail = (GCC_MemFunPtr*)&mfp; + out.thisptroffs = mfp_detail->delta; + if (mfp_detail->vtable_index_plus1 & 1) + { + out.vtblindex = (mfp_detail->vtable_index_plus1 - 1) / SH_PTRSIZE; + out.vtbloffs = 0; + out.isVirtual = true; + } + else + out.isVirtual = false; + } + }; + +# elif SH_COMP == SH_COMP_MSVC + + namespace + { + int MFI_GetVtblOffset(void *mfp) + { + unsigned char *addr = (unsigned char*)mfp; + if (*addr == 0xE9) // Jmp + { + // May or may not be! + // Check where it'd jump + addr += 5 /*size of the instruction*/ + *(unsigned long*)(addr + 1); + } + + // Check whether it's a virtual function call + // They look like this: + // 004125A0 8B 01 mov eax,dword ptr [ecx] + // 004125A2 FF 60 04 jmp dword ptr [eax+4] + // ==OR== + // 00411B80 8B 01 mov eax,dword ptr [ecx] + // 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h] + + // However, for vararg functions, they look like this: + // 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4] + // 0048F0B4 8B 00 mov eax,dword ptr [eax] + // 0048F0B6 FF 60 08 jmp dword ptr [eax+8] + // ==OR== + // 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4] + // 0048F0B4 8B 00 mov eax,dword ptr [eax] + // 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h] + + // With varargs, the this pointer is passed as if it was the first argument + + bool ok = false; + if (addr[0] == 0x8B && addr[1] == 0x44 && addr[2] == 0x24 && addr[3] == 0x04 && + addr[4] == 0x8B && addr[5] == 0x00) + { + addr += 6; + ok = true; + } + else if (addr[0] == 0x8B && addr[1] == 0x01) + { + addr += 2; + ok = true; + } + if (!ok) + return -1; + + if (*addr++ == 0xFF) + { + if (*addr == 0x60) + { + return *++addr / 4; + } + else if (*addr == 0xA0) + { + return *((unsigned int*)++addr) / 4; + } + else if (*addr == 0x20) + return 0; + else + return -1; + } + return -1; + } + } + + template<> struct MFI_Impl<1*SH_PTRSIZE> // simple ones + { + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + out.thisptroffs = 0; + out.vtbloffs = 0; + } + }; + + template<> struct MFI_Impl<2*SH_PTRSIZE> // more complicated ones! + { + struct MSVC_MemFunPtr2 + { + void *funcadr; + int delta; + }; + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + out.thisptroffs = reinterpret_cast(&mfp)->delta; + out.vtbloffs = 0; + } + }; + + // By Don Clugston, adapted + template<> struct MFI_Impl<3*SH_PTRSIZE> // WOW IT"S GETTING BIGGER OMGOMOGMG + { + class __single_inheritance GenericClass; + class GenericClass {}; + + struct MicrosoftVirtualMFP { + void (GenericClass::*codeptr)(); // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtable_index; // or 0 if no virtual inheritance + }; + + struct GenericVirtualClass : virtual public GenericClass + { + typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); + GenericVirtualClass * GetThis() { return this; } + }; + + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + // This pointer + /* + union { + MFP func; + GenericClass* (T::*ProbeFunc)(); + MicrosoftVirtualMFP s; + } u; + u.func = mfp; + union { + GenericVirtualClass::ProbePtrType virtfunc; + MicrosoftVirtualMFP s; + } u2; + + // Check that the horrible_cast<>s will work + typedef int ERROR_CantUsehorrible_cast[sizeof(mfp)==sizeof(u.s) + && sizeof(mfp)==sizeof(u.ProbeFunc) + && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; + // Unfortunately, taking the address of a MF prevents it from being inlined, so + // this next line can't be completely optimised away by the compiler. + u2.virtfunc = &GenericVirtualClass::GetThis; + u.s.codeptr = u2.s.codeptr; + out.thisptroffs = (reinterpret_cast(NULL)->*u.ProbeFunc)(); + */ + out.thisptroffs = -1; + out.vtbloffs = 0; + } + }; + + // Don: Nasty hack for Microsoft and Intel (IA32 and Itanium) + // unknown_inheritance classes go here + // This is probably the ugliest bit of code I've ever written. Look at the casts! + // There is a compiler bug in MSVC6 which prevents it from using this code. + template<> struct MFI_Impl<4*SH_PTRSIZE> // THE BIGGEST ONE!!!1GABEN + { + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + + // The member function pointer is 16 bytes long. We can't use a normal cast, but + // we can use a union to do the conversion. + union { + MFP func; + // In VC++ and ICL, an unknown_inheritance member pointer + // is internally defined as: + struct { + void *m_funcaddress; // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtordisp; // #bytes to add to 'this' to find the vtable + int vtable_index; // or 0 if no virtual inheritance + } s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(u.func)==sizeof(u.s)? 1 : -1]; + u.func = mfp; + int virtual_delta = 0; + if (u.s.vtable_index) { // Virtual inheritance is used + /* + // First, get to the vtable. + // It is 'vtordisp' bytes from the start of the class. + int * vtable = *reinterpret_cast( + reinterpret_cast(thisptr) + u.s.vtordisp ); + + // 'vtable_index' tells us where in the table we should be looking. + virtual_delta = u.s.vtordisp + *reinterpret_cast( + reinterpret_cast(vtable) + u.s.vtable_index); + // The int at 'virtual_delta' gives us the amount to add to 'this'. + // Finally we can add the three components together. Phew! + out.thisptr = reinterpret_cast( + reinterpret_cast(thisptr) + u.s.delta + virtual_delta); + */ + out.vtbloffs = u.s.vtordisp; + out.thisptroffs = -1; + } + else + { + out.vtbloffs = out.vtblindex < 0 ? 0 : u.s.delta; + out.thisptroffs = u.s.delta; + } + }; + }; +# else +# error Unsupported compiler +# endif + + // This version does not take a this pointer + // Useful for hookdecls, as they ensure that mfp is correct through a static_cast + template inline void GetFuncInfo(X mfp, MemFuncInfo &out) + { + MFI_Impl::GetFuncInfo(mfp, out); + } + + // Versions which do take a this + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(), MemFuncInfo &out) + { + RetType(Y::*mfp2)() = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)() const, MemFuncInfo &out) + { + RetType(Y::*mfp2)() const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + // GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it +#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300 + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + +#endif + +} + +#endif diff --git a/utils/mmsource/core-legacy/sourcehook/generate/sh_memfuncinfo.hxx b/utils/mmsource/core-legacy/sourcehook/generate/sh_memfuncinfo.hxx new file mode 100644 index 00000000..5ed37abe --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/sh_memfuncinfo.hxx @@ -0,0 +1,332 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2007 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +/** + * @brief This file provides a way for getting information about a member function. + * @file sh_memfuncinfo.h + */ + +#ifndef __SHINT_MEMFUNC_INFO_H__ +#define __SHINT_MEMFUNC_INFO_H__ + +namespace SourceHook +{ + + // Don Clugston: + // implicit_cast< > + // I believe this was originally going to be in the C++ standard but + // was left out by accident. It's even milder than static_cast. + // I use it instead of static_cast<> to emphasize that I'm not doing + // anything nasty. + // Usage is identical to static_cast<> + template + inline OutputClass implicit_cast(InputClass input){ + return input; + } + + + struct MemFuncInfo + { + bool isVirtual; // Is the function virtual? + int thisptroffs; // The this pointer the function expects to be called with + // If -1, you need to call the GetFuncInfo_GetThisPtr function + int vtblindex; // The function's index in the vtable (0-based, 1=second entry, 2=third entry, ...) + int vtbloffs; // The vtable pointer + }; + + // Ideas by Don Clugston. + // Check out his excellent paper: http://www.codeproject.com/cpp/FastDelegate.asp + + template struct MFI_Impl + { + template static inline void GetFuncInfo(MFP *mfp, MemFuncInfo &out) + { + static char weird_memfunc_pointer_exclamation_mark_arrow_error[N-1000]; + } + }; + +# if SH_COMP == SH_COMP_GCC + + template<> struct MFI_Impl<2*SH_PTRSIZE> // All of these have size==8/16 + { + struct GCC_MemFunPtr + { + union + { + void *funcadr; // always even + intptr_t vtable_index_plus1; // = vindex+1, always odd + }; + intptr_t delta; + }; + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + GCC_MemFunPtr *mfp_detail = (GCC_MemFunPtr*)&mfp; + out.thisptroffs = mfp_detail->delta; + if (mfp_detail->vtable_index_plus1 & 1) + { + out.vtblindex = (mfp_detail->vtable_index_plus1 - 1) / SH_PTRSIZE; + out.vtbloffs = 0; + out.isVirtual = true; + } + else + out.isVirtual = false; + } + }; + +# elif SH_COMP == SH_COMP_MSVC + + namespace + { + int MFI_GetVtblOffset(void *mfp) + { + unsigned char *addr = (unsigned char*)mfp; + if (*addr == 0xE9) // Jmp + { + // May or may not be! + // Check where it'd jump + addr += 5 /*size of the instruction*/ + *(unsigned long*)(addr + 1); + } + + // Check whether it's a virtual function call + // They look like this: + // 004125A0 8B 01 mov eax,dword ptr [ecx] + // 004125A2 FF 60 04 jmp dword ptr [eax+4] + // ==OR== + // 00411B80 8B 01 mov eax,dword ptr [ecx] + // 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h] + + // However, for vararg functions, they look like this: + // 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4] + // 0048F0B4 8B 00 mov eax,dword ptr [eax] + // 0048F0B6 FF 60 08 jmp dword ptr [eax+8] + // ==OR== + // 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4] + // 0048F0B4 8B 00 mov eax,dword ptr [eax] + // 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h] + + // With varargs, the this pointer is passed as if it was the first argument + + bool ok = false; + if (addr[0] == 0x8B && addr[1] == 0x44 && addr[2] == 0x24 && addr[3] == 0x04 && + addr[4] == 0x8B && addr[5] == 0x00) + { + addr += 6; + ok = true; + } + else if (addr[0] == 0x8B && addr[1] == 0x01) + { + addr += 2; + ok = true; + } + if (!ok) + return -1; + + if (*addr++ == 0xFF) + { + if (*addr == 0x60) + { + return *++addr / 4; + } + else if (*addr == 0xA0) + { + return *((unsigned int*)++addr) / 4; + } + else if (*addr == 0x20) + return 0; + else + return -1; + } + return -1; + } + } + + template<> struct MFI_Impl<1*SH_PTRSIZE> // simple ones + { + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + out.thisptroffs = 0; + out.vtbloffs = 0; + } + }; + + template<> struct MFI_Impl<2*SH_PTRSIZE> // more complicated ones! + { + struct MSVC_MemFunPtr2 + { + void *funcadr; + int delta; + }; + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + out.thisptroffs = reinterpret_cast(&mfp)->delta; + out.vtbloffs = 0; + } + }; + + // By Don Clugston, adapted + template<> struct MFI_Impl<3*SH_PTRSIZE> // WOW IT"S GETTING BIGGER OMGOMOGMG + { + class __single_inheritance GenericClass; + class GenericClass {}; + + struct MicrosoftVirtualMFP { + void (GenericClass::*codeptr)(); // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtable_index; // or 0 if no virtual inheritance + }; + + struct GenericVirtualClass : virtual public GenericClass + { + typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); + GenericVirtualClass * GetThis() { return this; } + }; + + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + // This pointer + /* + union { + MFP func; + GenericClass* (T::*ProbeFunc)(); + MicrosoftVirtualMFP s; + } u; + u.func = mfp; + union { + GenericVirtualClass::ProbePtrType virtfunc; + MicrosoftVirtualMFP s; + } u2; + + // Check that the horrible_cast<>s will work + typedef int ERROR_CantUsehorrible_cast[sizeof(mfp)==sizeof(u.s) + && sizeof(mfp)==sizeof(u.ProbeFunc) + && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; + // Unfortunately, taking the address of a MF prevents it from being inlined, so + // this next line can't be completely optimised away by the compiler. + u2.virtfunc = &GenericVirtualClass::GetThis; + u.s.codeptr = u2.s.codeptr; + out.thisptroffs = (reinterpret_cast(NULL)->*u.ProbeFunc)(); + */ + out.thisptroffs = -1; + out.vtbloffs = 0; + } + }; + + // Don: Nasty hack for Microsoft and Intel (IA32 and Itanium) + // unknown_inheritance classes go here + // This is probably the ugliest bit of code I've ever written. Look at the casts! + // There is a compiler bug in MSVC6 which prevents it from using this code. + template<> struct MFI_Impl<4*SH_PTRSIZE> // THE BIGGEST ONE!!!1GABEN + { + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + + // The member function pointer is 16 bytes long. We can't use a normal cast, but + // we can use a union to do the conversion. + union { + MFP func; + // In VC++ and ICL, an unknown_inheritance member pointer + // is internally defined as: + struct { + void *m_funcaddress; // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtordisp; // #bytes to add to 'this' to find the vtable + int vtable_index; // or 0 if no virtual inheritance + } s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(u.func)==sizeof(u.s)? 1 : -1]; + u.func = mfp; + int virtual_delta = 0; + if (u.s.vtable_index) { // Virtual inheritance is used + /* + // First, get to the vtable. + // It is 'vtordisp' bytes from the start of the class. + int * vtable = *reinterpret_cast( + reinterpret_cast(thisptr) + u.s.vtordisp ); + + // 'vtable_index' tells us where in the table we should be looking. + virtual_delta = u.s.vtordisp + *reinterpret_cast( + reinterpret_cast(vtable) + u.s.vtable_index); + // The int at 'virtual_delta' gives us the amount to add to 'this'. + // Finally we can add the three components together. Phew! + out.thisptr = reinterpret_cast( + reinterpret_cast(thisptr) + u.s.delta + virtual_delta); + */ + out.vtbloffs = u.s.vtordisp; + out.thisptroffs = -1; + } + else + { + out.vtbloffs = out.vtblindex < 0 ? 0 : u.s.delta; + out.thisptroffs = u.s.delta; + } + }; + }; +# else +# error Unsupported compiler +# endif + + // This version does not take a this pointer + // Useful for hookdecls, as they ensure that mfp is correct through a static_cast + template inline void GetFuncInfo(X mfp, MemFuncInfo &out) + { + MFI_Impl::GetFuncInfo(mfp, out); + } + + // Versions which do take a this +@[$1,0,$a: + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(@[$2,1,$1|, :Param$2@]), MemFuncInfo &out) + { + RetType(Y::*mfp2)(@[$2,1,$1|, :Param$2@]) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(@[$2,1,$1|, :Param$2@]) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(@[$2,1,$1|, :Param$2@]) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } +@] + + // GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it +#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300 + +@[$1,0,$a: + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + +@] + +#endif + +} + +#endif diff --git a/utils/mmsource/core-legacy/sourcehook/generate/shworker.bin b/utils/mmsource/core-legacy/sourcehook/generate/shworker.bin new file mode 100644 index 0000000000000000000000000000000000000000..63b8d5233837bf9393b75edd185a1b67c49a2c0b GIT binary patch literal 59291 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 gc`~ch(jOWgiqQg>v#c2F#rGn literal 0 HcmV?d00001 diff --git a/utils/mmsource/core-legacy/sourcehook/generate/shworker/Makefile b/utils/mmsource/core-legacy/sourcehook/generate/shworker/Makefile new file mode 100644 index 00000000..86ac5bf9 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/shworker/Makefile @@ -0,0 +1,13 @@ +default: shworker + +bin: + mkdir bin + +fd_hopter.o: fd_hopter.cpp bin + gcc -fPIC -O2 -o bin/$@ -c $< + +main.o: shworker.cpp bin + gcc -fPIC -O2 -o bin/$@ -c $< + +shworker: fd_hopter.o main.o bin + gcc -ldl -lstdc++ bin/fd_hopter.o bin/main.o -o bin/shworker.bin diff --git a/utils/mmsource/core-legacy/sourcehook/generate/shworker/fd_hopter.cpp b/utils/mmsource/core-legacy/sourcehook/generate/shworker/fd_hopter.cpp new file mode 100644 index 00000000..7fc149d6 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/shworker/fd_hopter.cpp @@ -0,0 +1,370 @@ +// From fastdelegate +// http://www.codeproject.com/cpp/FastDelegate.asp + +// Modified to be run from shworker by PM + + +// HOPTER.EXE -- A simple header generator for vararg templates +/* MOTIVATION + C++ doesn't have a vararg feature for templates. This can be a + nuisance when writing class libraries. There are a few options: + (a) manually repeat code. This is tedious and error prone. + (b) Use macros. Messy, can't cope with template + arguments, and users get hard-to-interpret error messages. + (c) Use the boost preprocessor library. This slows compilation, + and introduces a dependency on boost. + (d) Write a program to automatically generate the code. + I've never seen a general program to do this job, so this is + a very simple command-line program to do it. + + Why is it called Hopter? + I wanted a word that started with h, to be reminiscent of header + files. At the time, my 2yo son kept talking about 'Hopter Copters' + (he couldn't pronounce 'helicopter'). + It also reflects the level of sophistication of this program -- + it was named by a two year old. + + IMPLEMENTATION + + When you analyze the problem, you find that the requirements + are very simple. + Varargs are needed in two places: templates and functions. + You want to use them in two ways: when declaring the template + or function, and when invoking the function / selecting the + template. + + It's a brain-dead implementation, which just does a search-and-replace + of specific strings. It could be done with a few lines using sed on + a *NIX platform. Because I use Windows, I've done a quick and dirty + implementation using CString. + +In a file, @VARARGS at the start of a line indicates the start of the code +to be expanded. @ENDVAR at the start of a line marks the end of the +expansion. + + declare template -- template <@CLASSARGS> class SomeClass + template + class SomeClass + + declare function -- somefunc(@FUNCARGS) + somefunc(Param1 p1, Param2 p2) + + select template -- SomeClass<@SELARGS> + SomeClass + + invoke function -- somefunc(@INVOKEARGS) + somefunc(p1, p2) + + I also provide @NUM which is the number of arguments. + The case where @NUM is zero is a special case: for template declarations, + the entire template<> bit needs to disappear. When other arguments are + involved, either at the beginning or end of the list, there a commas + which might need to be removed. + + I've used .hxx as the extension for these files. This enables C++ + I wanted to use an unusual file extension (.HOH) for these files, because they + aren't real header files. But I also like to use the C++ syntax highlighting + in Visual Studio. I chose .hxx because MSVC treats it as C++, but it + seems to very rarely used. + + Installation (for VC6, if you want to use .HOH as the extension instead): + Go into the registry and change + HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Text Editor\Tabs/Language Settings\C/C++\FileExtensions from cpp;cxx;c;h;hxx;hpp;inl;tlh;tli;rc;rc2 + to cpp;cxx;c;h;hxx;hpp;inl;tlh;tli;rc;rc2;hoh by adding “;hoh” to the end. + Then add this as a custom build step to the main file of your project: + hopter $(InputDir)\*.hoh $(InputDir)\*.h + +*/ + +#include +#include +#include + +// This is a quick-n-dirty implementation of a CString replacement. +// It promises nothing more than to provide enough functionality to get +// this program to run. +// Note that I have really never used CString, so the information to +// implement the members that are used in this program come from +// online documentation at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmfc98/html/_mfc_cstring.asp +// Also, I have only used VC++ a few times, a long time ago, so +// I really do not know what all their alphabet soup is suppoed to +// mean, so I just made a guess... + + +class CString +{ +public: + enum { MAX_FORMAT_STRING_SIZE = 8 * 1044 }; + CString() + : str_() + { + } + + CString( + CString const & rhs) + : str_(rhs.str_) + { + } + + CString( + char ch, + int repeat = 1) + : str_(repeat, ch) + { + } + + CString( + char const * s) + : str_(s) + { + } + + CString & operator=( + CString const & rhs) + { + str_ = rhs.str_; + return *this; + } + + CString & operator=( + char const * s) + { + str_ = s; + return *this; + } + + CString & operator=( + char ch) + { + str_ = ch; + return *this; + } + + void Format( + char const * fmt, + ...) + { + char buffer[ MAX_FORMAT_STRING_SIZE ]; + va_list ap; + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + str_ = buffer; + } + + char operator[]( + int x) const + { + return str_[x]; + } + + CString & operator+=( + CString const & x) + { + str_ += x.str_; return *this; + } + + int Replace( + CString const & lhs, + CString const & rhs) + { + int rval = 0; + std::string::size_type pos = 0; + while (pos < str_.length()) + { + pos = str_.find(lhs.str_, pos); + if (pos != std::string::npos) + { + str_.replace(pos, lhs.GetLength(), rhs.str_); + pos += rhs.GetLength(); + ++rval; + } + } + return rval; + } + + int GetLength() const + { + return str_.length(); + } + + operator char const * () const + { + return str_.c_str(); + } + +private: + std::string str_; +}; + + +CString operator+( + CString const & x, + CString const & y) +{ + CString result(x); + result += y; + return result; +} + + +/* Example: This is an excerpt from boost::function_template.hpp + +#define BOOST_FUNCTION_FUNCTION_INVOKER \ + BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \ + BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS) + + template< + typename FunctionPtr, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_GET_FUNCTION_INVOKER + { + typedef typename ct_if<(is_void::value), + BOOST_FUNCTION_VOID_FUNCTION_INVOKER< + FunctionPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >, + BOOST_FUNCTION_FUNCTION_INVOKER< + FunctionPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + > + >::type type; + }; + +Using HOPTER, this can be written as: + + template< typename FunctionPtr, typename R, @CLASSARGS> + struct get_function_invoker@NUM + { + typedef typename ct_if<(is_void::value), + void_function_invoker@NUM, + function_invoker@NUM + >::type type; + }; +*/ + +int MaxNumArgs; + +/// Makes the necessary subsititutions in 'bigblock', and writes to fout. +void PrintVarArgs(FILE *fout, CString bigblock, int num) { + CString numstr; + CString invokelist; + CString funclist; + CString selectlist; + CString classlist; + CString commastr; + numstr.Format("%d", num); + if (num==0) { + invokelist=""; + funclist=""; + selectlist=""; + commastr=""; + classlist=""; + }else { + invokelist="p1"; + funclist="Param1 p1"; + selectlist = "Param1"; + classlist = "class Param1"; + commastr=", "; + CString str; + for (int k=2; k<=num; k++) { + str.Format(", p%d", k); + invokelist+=str; + str.Format(", Param%d p%d", k, k); + funclist+=str; + str.Format(", Param%d", k); + selectlist += str; + str.Format(", class Param%d", k); + classlist += str; + } + } + + // Simple replacement of number of arguments + bigblock.Replace("@NUM", numstr); + + // Template declarations + if (num==0) bigblock.Replace("template<@CLASSARGS>", ""); + else bigblock.Replace("template<@CLASSARGS>", + (CString)"template<" + classlist+">"); + if (num==0) bigblock.Replace("template <@CLASSARGS>", ""); + else bigblock.Replace("template <@CLASSARGS>", + (CString)"template<" + classlist+">"); + bigblock.Replace(",@CLASSARGS", commastr + classlist); + bigblock.Replace(", @CLASSARGS", commastr + classlist); + bigblock.Replace("@CLASSARGS, ", classlist + commastr); + bigblock.Replace("@CLASSARGS,", classlist + commastr); + bigblock.Replace("@CLASSARGS", classlist); + + // Template selections + CString selargstr; + if (num==0) selargstr = ""; + else selargstr = (CString)"<"+selectlist+">"; + + bigblock.Replace("<@SELARGS>", selargstr); + bigblock.Replace("< @SELARGS >", selargstr); + bigblock.Replace(",@SELARGS", commastr + selectlist); + bigblock.Replace(", @SELARGS", commastr + selectlist); + bigblock.Replace("@SELARGS, ", selectlist + commastr); + bigblock.Replace("@SELARGS,", selectlist + commastr); + bigblock.Replace("@SELARGS", selectlist); + + // Function declarations + bigblock.Replace(",@FUNCARGS", commastr + funclist); + bigblock.Replace(", @FUNCARGS", commastr + funclist); + bigblock.Replace("@FUNCARGS, ", funclist + commastr); + bigblock.Replace("@FUNCARGS,", funclist + commastr); + bigblock.Replace("@FUNCARGS", funclist); + + // Function invocation + bigblock.Replace(",@INVOKEARGS", commastr + invokelist); + bigblock.Replace(", @INVOKEARGS", commastr + invokelist); + bigblock.Replace("@INVOKEARGS, ", invokelist + commastr); + bigblock.Replace("@INVOKEARGS,", invokelist + commastr); + bigblock.Replace("@INVOKEARGS", invokelist); + + fprintf(fout, bigblock); +} + +int action_hopter(int numargs, const char *filenamein, const char *filenameout) +{ + + MaxNumArgs = numargs; + + FILE * fin; + FILE *fout; + + fin =fopen(filenamein,"rt"); + if (!fin) { printf("Error, can't open %s\n", filenamein); return 1; }; + fout = fopen (filenameout, "wt"); + if (!fout) { printf("Error, can't open %s\n", filenameout); return 1; }; + char buf[5000]; + for (;;) { + if (!fgets(buf, 5000, fin)) break; + if (!strncmp(buf, "@VARARGS", 8)) { + // found a match... + CString bigblock; + for (;;) { + if (feof(fin)) { printf("No matching @ENDVAR !!??\n"); return 1; }; + fgets(buf, 5000, fin); + if (!strncmp(buf, "@ENDVAR", 7)) break; + bigblock+=buf; + } +// fprintf(fout, "// Auto-generated code [[[\n"); + for (int k=0; k<=MaxNumArgs; k++) { + fprintf(fout, "//N=%d\n", k); + PrintVarArgs(fout, bigblock, k); + } +// fprintf(fout, "// ]]] End auto-generated code\n"); + } else { + fprintf(fout, "%s", buf); + } + } + fclose(fin); + fclose(fout); + return 0; +} diff --git a/utils/mmsource/core-legacy/sourcehook/generate/shworker/msvc7/shworker.vcproj b/utils/mmsource/core-legacy/sourcehook/generate/shworker/msvc7/shworker.vcproj new file mode 100644 index 00000000..1218a8ef --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/shworker/msvc7/shworker.vcproj @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/utils/mmsource/core-legacy/sourcehook/generate/shworker/msvc8/shworker.vcproj b/utils/mmsource/core-legacy/sourcehook/generate/shworker/msvc8/shworker.vcproj new file mode 100644 index 00000000..6f0ca43b --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/shworker/msvc8/shworker.vcproj @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/utils/mmsource/core-legacy/sourcehook/generate/shworker/shworker.cpp b/utils/mmsource/core-legacy/sourcehook/generate/shworker/shworker.cpp new file mode 100644 index 00000000..5e0047ce --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/shworker/shworker.cpp @@ -0,0 +1,767 @@ +// SHWorker +// Inspired by "Hopter" that comes with FastDelegate (http://www.codeproject.com/cpp/FastDelegate.asp) +// Much more powerful (and ugly) though + +/* + + INPUT FILE DIRECTIVES + + $a is the first additional argument, $b the second, ... + + --- + ITERATION + + @[variable,min,max:code|separator@] + + variable: this will be replaced in code by its current value. + vars are always $ and a number. + min: first value to be used for variable + max: last value to be used for variable + code: the code that will be inserted on each iteration. + separator: optional. this will be inserted between iterations. + If you don't use a separator, you may leave out the | + IMPORTANT: iterations will only be performed if max >= min + + --- ARITHMETIC EXPRESSION + + @(expr) + + expr may contain: + variables + constants + operators (currently only + and * are supported) + + --- CONDITION + + @[expr operator expr:code@] + + Example: @[$1!=0:hello@] + + Currently only != and == are supported operators. + + + Yes, error handling in here is weird, some stuff uses return values, other code uses exceptions. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "stdio.h" + +#ifdef __linux__ +# define stricmp strcasecmp +#endif + +// Ensure that the template version is being used! +#ifdef min +#undef min +#endif + +using namespace std; + +extern int action_hopter(int numargs, const char *filenamein, const char *filenameout); + +typedef map varmap; + +struct MyError +{ + const char *m_desc; + + MyError(const char *desc) : m_desc(desc) + { + } + + void Print() + { + cout << m_desc << endl; + } +}; + +struct SyntaxError : MyError +{ + SyntaxError() : MyError("Syntax error in expression") + { + } +}; +struct OtherError : MyError +{ + OtherError() : MyError("WTF") + { + } +}; + +void trim_string(std::string &str) +{ + size_t first = str.find_first_not_of(" \t\v\n\r"); + if (first == std::string::npos) + { + str.clear(); + return; + } + + size_t last = str.length(); + for (std::string::reverse_iterator riter = str.rbegin(); riter != str.rend(); ++riter) + { + char ch = *riter; + if (ch != ' ' && + ch != '\t' && + ch != '\v' && + ch != '\n' && + ch != '\r') + break; + --last; + } + str = str.substr(first, last - first); +} + +// unused +bool ExtractToken(std::string &strin, std::string &strout) +{ + trim_string(strin); + if (strin.begin() == strin.end()) + { + strout.clear(); + return false; + } + size_t first = strin.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFHIJKLMNOPQRSTUVWXYZ_0123456789"); + if (first == 0) + { + if (strin.size() > 1 && strin.at(0) == '/' && strin.at(1) == '/') + { + // One-line comment, find its end + first = strin.find('\n') + 1; + } + else if (strin.size() > 1 && strin.at(0) == '/' && strin.at(1) == '*') + { + // Multi-line comment, find its end + first = strin.find("*/") + 2; + } + strin = strin.substr(1); + strout.clear(); + return true; + } + strout = strin.substr(0, first); + strin = strin.substr(first); + return true; +} + +// Returns the number of occurencies replaced +int DoReplace(string &str, const string &what, const string &with) +{ + int cnt=0; + size_t where = str.find(what); + + while (where != string::npos) + { + str.replace(where, what.size(), with); + ++cnt; + where = str.find(what, where); + } + return cnt; +} + +int DoReplace(string &str, const char *what, const char *with) +{ + int cnt=0; + size_t where = str.find(what); + size_t whatsize = strlen(what); + while (where != string::npos) + { + str.replace(where, whatsize, with); + ++cnt; + where = str.find(what, where); + } + return cnt; +} + + +class ExprParser +{ + // grammar: + /* + expr -> expr + term { do_add } + | expr - term { do_sub } + | term + + term -> term * factor { do_mul } + | term / factor { do_div } + | term % factor { do_mod } + + factor -> (expr) + | numeric constant { push } + + + equivalent to: + + expr -> term moreterms + moreterms -> + term { do_add } moreterms + moreterms -> - term { do_sub } moreterms + moreterms -> epsilon + + term -> factor morefactors + morefactors -> * factor { do_mul } morefactors + morefactors -> / factor { do_div } morefactors + morefactors -> % factor { do_mod } morefactors + morefactors -> epsilon + + factor -> (expr) + factor -> numeric constant { push } + + */ + + string::const_iterator m_begin; + string::const_iterator m_end; + string::const_iterator m_iter; + + int m_lookahead; + int m_tokenval; + + stack m_stack; + static const int DONE = 256; + static const int NUM = 257; + + int lexan() + { + while (1) + { + if (m_iter == m_end) + return DONE; + + int t = *m_iter++; + + if (t == ' ' || t == '\t') + ; // Remove whitespace + else if (isdigit(t)) + { + --m_iter; + + m_tokenval = 0; + while (m_iter != m_end && isdigit(*m_iter)) + { + m_tokenval *= 10; + m_tokenval += *m_iter - '0'; + ++m_iter; + } + return NUM; + } + else + return t; + } + } + + void match(int t) + { + if (m_lookahead == t) + m_lookahead = lexan(); + else + throw SyntaxError(); + } + void factor() + { + switch (m_lookahead) + { + case '(': + match('('); expr(); match(')'); + break; + case NUM: + m_stack.push(m_tokenval); match(NUM); + break; + default: + throw SyntaxError(); + } + } + void term() + { + factor(); + while (1) + { + switch (m_lookahead) + { + case '*': + match('*'); factor(); do_mul(); + continue; + case '/': + match('/'); factor(); do_div(); + continue; + case '%': + match('%'); factor(); do_mod(); + continue; + default: + return; + } + + } + } + + void expr() + { + term(); + while (1) + { + switch (m_lookahead) + { + case '+': + match('+'); term(); do_add(); + continue; + case '-': + match('-'); term(); do_sub(); + continue; + default: + return; + } + } + } + + void do_add() + { + int a2 = m_stack.top(); m_stack.pop(); + int a1 = m_stack.top(); m_stack.pop(); + m_stack.push(a1 + a2); + } + + void do_sub() + { + int a2 = m_stack.top(); m_stack.pop(); + int a1 = m_stack.top(); m_stack.pop(); + m_stack.push(a1 - a2); + } + + void do_mul() + { + int a2 = m_stack.top(); m_stack.pop(); + int a1 = m_stack.top(); m_stack.pop(); + m_stack.push(a1 * a2); + } + + void do_div() + { + int a2 = m_stack.top(); m_stack.pop(); + int a1 = m_stack.top(); m_stack.pop(); + m_stack.push(a1 / a2); + } + + void do_mod() + { + int a2 = m_stack.top(); m_stack.pop(); + int a1 = m_stack.top(); m_stack.pop(); + m_stack.push(a1 % a2); + } + +public: + ExprParser(string::const_iterator begin, string::const_iterator end) : + m_begin(begin), m_end(end), m_iter(begin) + { + m_lookahead = lexan(); + expr(); + } + + operator int() + { + if (m_stack.size() != 1) + throw OtherError(); + + return m_stack.top(); + } +}; + +int parse_expr(string::const_iterator begin, string::const_iterator end) +{ + return ExprParser(begin, end); +} + +size_t find_first_directive(const string &buf, size_t begin=0) +{ + for (;;) + { + if (begin >= buf.size()) + return string::npos; + + size_t firstdirpos = buf.find('@', begin); + if (firstdirpos == string::npos) + return firstdirpos; + + if (buf.size() > firstdirpos+1) + { + if (buf[firstdirpos+1] == '[' || buf[firstdirpos+1] == '(') + return firstdirpos; + } + begin = firstdirpos+1; + } +} + +// buf begins with a section. Find its end! +size_t find_section_end(const string &buf) +{ + int starttype = buf[1]; + int endtype = (buf[1] == '(') ? ')' : ']'; + + int nestlevel = 0; + + if (starttype == '(') + { + for (string::const_iterator iter = buf.begin(); iter != buf.end(); ++iter) + { + if (*iter == starttype) + ++nestlevel; + if (*iter == endtype) + { + if (--nestlevel == 0) + return iter - buf.begin() + 1; + } + } + return string::npos; + } + else if (starttype == '[') + { + int lastchar = 0; + for (string::const_iterator iter = buf.begin(); iter != buf.end(); ++iter) + { + if (lastchar == '@' && *iter == starttype) + ++nestlevel; + if (lastchar == '@' && *iter == endtype) + { + if (--nestlevel == 0) + return iter - buf.begin() + 1; + } + lastchar = *iter; + } + return string::npos; + } + + return string::npos; +} + +// replaces variables and additional arguments +void replace_vars(string &buf, int argc, int *argv, const varmap &vars) +{ + char varname[] = "$ "; + char value[32]; + + for (int i = 0; i < argc; ++i) + { + varname[1] = 'a' + i; + sprintf(value, "%d", argv[i]); + DoReplace(buf, varname, value); + } + + for (varmap::const_iterator iter = vars.begin(); iter != vars.end(); ++iter) + { + varname[1] = '0' + iter->first; + sprintf(value, "%d", iter->second); + DoReplace(buf, varname, value); + } +} + +// do_input +// params: +// argc: number of additional arguments +// argv: additional arguments +// outfile: output file +// buf: string to be processed. IMPORTANT: buf is modified! +// curvars: variables buffer. +// retval: +// 0 on success, non-zero on error + +int do_input(int argc, int *argv, ofstream &outfile, string &buf, varmap &curvars) +{ + for (;;) + { + // Find the next directive. + size_t firstdirpos = find_first_directive(buf); + + // Output everything that came before, and remove it from buf + outfile << buf.substr(0, firstdirpos); + if (firstdirpos == string::npos) + return 0; + buf = buf.substr(firstdirpos); + + // Now find the matching end. + size_t sectionend = find_section_end(buf); + if (sectionend == string::npos) + { + cout << "ERROR: Section not closed!" << endl; + return 1; + } + + // Place the section in its own buffer and remove it from the input string. + string sect(buf.begin(), buf.begin() + sectionend); + buf = buf.substr(sectionend); + + // CASE1: Arithmetic expression + if (sect[1] == '(') + { + replace_vars(sect, argc, argv, curvars); + outfile << parse_expr(sect.begin()+1, sect.end()); + } + else if (sect[1] == '[') + { + int is_iter = 0; // 0 -> no; 1 -> maybe (only used in check); 2 -> yes + char lastchar = 0; + // This could be an iteration OR a conditional thing. + // Pretty braindead check: iterations begin with a variable, then a comma. + for (string::iterator iter = sect.begin() + 2; iter != sect.end(); ++iter) + { + if (*iter == ' ' || *iter == '\t') + ; + else if (is_iter == 0 && lastchar == '$' && isdigit(*iter)) + is_iter = 1; + else if (is_iter == 1 && *iter == ',') + { + is_iter = 2; + break; + } + else if (*iter == '$') + ; + else + break; + lastchar = *iter; + } + if (is_iter == 2) + { + // CASE2: iteration + // Looks like: @[var,min,max:code|sep@] + // Replace known variables / additional arguments + replace_vars(sect, argc, argv, curvars); + + // get the parts! + string varname; + int varnum; + int expr_min; + int expr_max; + + // varname + size_t comma = sect.find(','); + if (comma == string::npos) + { + cout << "Invalid iteration syntax" << endl; + return 1; + } + varname.assign(sect.begin() + 2, sect.begin() + comma); + trim_string(varname); + if (varname.size() != 2 || varname[0] != '$' || !isdigit(varname[1])) + { + cout << "Invalid variable name" << endl; + return 1; + } + varnum = varname[1] - '0'; + + // min + ++comma; + size_t nextcomma = sect.find(',', comma); + if (nextcomma == string::npos) + { + cout << "Invalid iteration syntax" << endl; + return 1; + } + expr_min = parse_expr(sect.begin() + comma, sect.begin() + nextcomma); + + // max + comma = nextcomma + 1; + nextcomma = sect.find(':', comma); + if (nextcomma == string::npos) + { + cout << "Invalid iteration syntax" << endl; + return 1; + } + + expr_max = parse_expr(sect.begin() + comma, sect.begin() + nextcomma); + + // separator + size_t sepbegin = sect.find('|'); + size_t sepend = string::npos; + if (sepbegin != string::npos && sepbegin < nextcomma) + { + // There's a separator! + ++sepbegin; + sepend = nextcomma; + } + else + sepbegin = string::npos; + + + ++nextcomma; // nextcomma is now where code begins! + + size_t codeend = sect.size() - 2; + + // Check whether the var is already taken + if (curvars.find(varnum) != curvars.end()) + { + cout << "Variable $" << varnum << "already taken!" << endl; + return 1; + } + + // Do iterations!! + for (int i = expr_min; i <= expr_max; ++i) + { + curvars[varnum] = i; + + string code(sect.begin() + nextcomma, sect.begin() + codeend); + replace_vars(code, argc, argv, curvars); + + // Feed it through the input routine (RECURSE!!!!!! YEAH!) + do_input(argc, argv, outfile, code, curvars); + + // Add separator if required + if (sepbegin != string::npos && i != expr_max) + { + string tmp(sect.begin() + sepbegin, sect.begin() + sepend); + do_input(argc, argv, outfile, tmp, curvars); + } + } + // Remove the var! + curvars.erase(varnum); + } + else + { + // CASE3: conditional thing. + // Looks like: @[expr1 operator expr2:code@] + + // Find the operator position + + enum OP_TYPE + { + OP_EQ, + OP_NEQ + }; + + OP_TYPE op; + size_t oppos = sect.find("=="); + if (oppos != string::npos) + op = OP_EQ; + else + { + oppos = sect.find("!="); + if (oppos != string::npos) + op = OP_NEQ; + else + { + cout << "Conditional expression without operator!?" << endl; + return 1; + } + } + size_t colon = sect.find(':'); + + // Now we've got everything. Parse first expr: + int expr1 = parse_expr(sect.begin() + 2, sect.begin() + oppos); + int expr2 = parse_expr(sect.begin() + oppos + 2, sect.begin() + colon); + if ((op == OP_EQ && expr1 == expr2) || + (op == OP_NEQ && expr1 != expr2)) + { + // Condition is true, process it! + // The text may still contain arithmetic exprs or other cond. exprs + // so send it through do_input + string tmp(sect.substr(colon+1, sect.size() - colon - 3)); + do_input(argc, argv, outfile, tmp, curvars); + } + } + } + else + { + cout << "WTF" << endl; + return 1; + } + } + + return 0; +} + + + +// action_iter +// params: +// filenamein: input file name +// filenameout: output file name +// argc: number of additional arguments +// argv: additional arguments +// retval: 0 on success, non-zero on error + +// Convert additional arguments +// Read whole input file to memory and open output file +// Pass to do_input() +int action_iter(const char *filenamein, const char *filenameout, int argc, const char *argv[]) +{ + // Convert additional arguments + const int MAX_ARGC = 10; + int converted_argv[MAX_ARGC]; + + int i; + for (i = 0; i < argc && i < MAX_ARGC; ++i) + converted_argv[i] = atoi(argv[i]); + + if (argc != i) + cout << "WARNING: Not all additional arguments processed!" << endl; + + + // Read whole input file to memory and open output file + ifstream fin(filenamein); + ofstream fout(filenameout); + + if (!fin) + { + cout << "Could not open file \"" << filenamein << "\"." << endl; + return 1; + } + if (!fout) + { + cout << "Could not open file \"" << filenameout << "\"." << endl; + return 1; + } + string input_str( + istreambuf_iterator (fin.rdbuf()), + istreambuf_iterator ()); + + + // Begin processing input + varmap vars; + try + { + return do_input(argc, converted_argv, fout, input_str, vars); + } + catch (MyError err) + { + err.Print(); + return 1; + } +} + +// MAIN +// Prints usage if required +// Calls action_hopter OR action_iter +int main(int argc, const char **argv) +{ + if (argc < 4) + { + cout << "Usage:" << endl << " shworker [iter/hopter] ..." << endl; + cout << " shworker iter filename.in filename.out [param1, param2, ...]" << endl; + cout << " shworker hopter filename.in filename.out [num-of-args]" << endl; + return 1; + } + + const char *action = argv[1]; + + if (stricmp(action, "hopter") == 0) + { + const char *filenamein = argv[2]; + const char *filenameout = argv[3]; + int argsnum = atoi(argv[4]); + + return action_hopter(argsnum, filenamein, filenameout); + } + else if (stricmp(action, "iter") == 0) + { + const char *filenamein = argv[2]; + const char *filenameout = argv[3]; + int additional_argc = argc - 4; + const char ** additional_argv = argv + 4; + return action_iter(filenamein, filenameout, additional_argc, additional_argv); + } + else + { + cout << "Unrecognized action: " << argv[1] << endl; + return 1; + } +} diff --git a/utils/mmsource/core-legacy/sourcehook/generate/sourcehook.h b/utils/mmsource/core-legacy/sourcehook/generate/sourcehook.h new file mode 100644 index 00000000..cc939001 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/sourcehook.h @@ -0,0 +1,6537 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2007 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +/** +* @file sourcehook.h +* @brief Contains the public SourceHook API +*/ + +#ifndef __SOURCEHOOK_H__ +#define __SOURCEHOOK_H__ + +// Interface revisions: +// 1 - Initial revision +// 2 - Changed to virtual functions for iterators and all queries +// 3 - Added "hook loop status variable" +// 4 - Reentrant +#define SH_IFACE_VERSION 4 + +// Impl versions: +// ??? +// 4 - addition of hook ids and vp hooks (with them, AddHookNew and RemoveHookNew) +// This is not a SH_IFACE_VERSION change so that old plugins continue working! +// 5 - addition of direct vp hooks (new hook mode; from now on AddHookNew checks for +// invalid hookmode -> impl version won't have to change because of things like this) +#define SH_IMPL_VERSION 4 + +// Hookman version: +// 1 - Support for recalls, performance optimisations +#define SH_HOOKMAN_VERSION 1 + +// The value of SH_GLOB_SHPTR has to be a pointer to SourceHook::ISourceHook +// It's used in various macros +#ifndef SH_GLOB_SHPTR +#define SH_GLOB_SHPTR g_SHPtr +#endif + +// Used to identify the current plugin +#ifndef SH_GLOB_PLUGPTR +#define SH_GLOB_PLUGPTR g_PLID +#endif + +#ifdef SH_DEBUG +# include +# include + +# define SH_ASSERT(x, info) \ + do { \ + if (!(x)) \ + { \ + printf("SOURCEHOOK DEBUG ASSERTION FAILED: %s:%u(%s): %s: ", __FILE__, __LINE__, __FUNCTION__, #x); \ + printf info; \ + putchar('\n'); \ + abort(); \ + } \ + } while(0) + +#else +# define SH_ASSERT(x, info) +#endif + +// System +#define SH_SYS_WIN32 1 +#define SH_SYS_LINUX 2 + +#ifdef _WIN32 +# define SH_SYS SH_SYS_WIN32 +#elif defined __linux__ +# define SH_SYS SH_SYS_LINUX +#else +# error Unsupported system +#endif + +// Compiler +#define SH_COMP_GCC 1 +#define SH_COMP_MSVC 2 + +#ifdef _MSC_VER +# define SH_COMP SH_COMP_MSVC +#elif defined __GNUC__ +# define SH_COMP SH_COMP_GCC +#else +# error Unsupported compiler +#endif + +#if SH_COMP==SH_COMP_MSVC && _MSC_VER < 1500 +# define vsnprintf _vsnprintf +#endif + +#if SH_SYS != SH_SYS_WIN32 +# include +#endif + +#define SH_PTRSIZE sizeof(void*) + +#include "FastDelegate.h" +#include "sh_memfuncinfo.h" + +// Good old metamod! + +// Flags returned by a plugin's api function. +// NOTE: order is crucial, as greater/less comparisons are made. +enum META_RES +{ + MRES_IGNORED=0, // plugin didn't take any action + MRES_HANDLED, // plugin did something, but real function should still be called + MRES_OVERRIDE, // call real function, but use my return value + MRES_SUPERCEDE // skip real function; use my return value +}; + + +namespace SourceHook +{ + /** + * @brief Specifies the size (in bytes) for the internal buffer of vafmt(printf-like) function handlers + */ + const int STRBUF_LEN=4096; + + /** + * @brief An empty class. No inheritance used. Used for original-function-call hacks + */ + class EmptyClass + { + }; + + /** + * @brief Implicit cast. + */ + template + inline Out implicit_cast(In input) + { + return input; + } + + /** + * @brief A plugin typedef + * + * SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it and every + * plugin has a unique identifier, everything is ok. + * It should also be possible to set it to 0. + */ + typedef int Plugin; + + struct ProtoInfo + { + ProtoInfo(int rtsz, int nop, const int *p) : beginningNull(0), retTypeSize(rtsz), numOfParams(nop), params(p) + { + } + int beginningNull; //!< To distinguish from old protos (which never begin with 0) + int retTypeSize; //!< 0 if void + int numOfParams; //!< number of parameters + const int *params; //!< params[0]=0 (or -1 for vararg), params[1]=size of first param, ... + }; + + /** + * @brief Specifies the actions for hook managers + */ + enum HookManagerAction + { + HA_GetInfo = 0, //!< Store info about the hook manager + HA_Register, //!< Save the IHookManagerInfo pointer for future reference + HA_Unregister //!< Clear the saved pointer + }; + + struct IHookManagerInfo; + + /** + * @brief Pointer to hook manager interface function + * + * A "hook manager" is a the only thing that knows the actual protoype of the function at compile time. + * + * @param ha What the hook manager should do + * @param hi A pointer to IHookManagerInfo + */ + typedef int (*HookManagerPubFunc)(HookManagerAction ha, IHookManagerInfo *hi); + + class ISHDelegate + { + public: + virtual void DeleteThis() = 0; // Ugly, I know + virtual bool IsEqual(ISHDelegate *other) = 0; + }; + + template class CSHDelegate : public ISHDelegate + { + T m_Deleg; + public: + CSHDelegate(T deleg) : m_Deleg(deleg) + { + } + + CSHDelegate(const CSHDelegate &other) : m_Deleg(other.m_Deleg) + { + } + + void DeleteThis() + { + delete this; + } + + bool IsEqual(ISHDelegate *other) + { + return static_cast* >(other)->GetDeleg() == GetDeleg(); + } + + T &GetDeleg() + { + return m_Deleg; + } + }; + + struct IHookList + { + struct IIter + { + virtual bool End() = 0; + virtual void Next() = 0; + virtual ISHDelegate *Handler() = 0; + virtual int ThisPtrOffs() = 0; + }; + virtual IIter *GetIter() = 0; + virtual void ReleaseIter(IIter *pIter) = 0; + }; + + struct IIface + { + virtual void *GetPtr() = 0; + virtual IHookList *GetPreHooks() = 0; + virtual IHookList *GetPostHooks() = 0; + }; + + struct IVfnPtr + { + virtual void *GetVfnPtr() = 0; + virtual void *GetOrigEntry() = 0; + + virtual IIface *FindIface(void *ptr) = 0; + }; + + struct IHookManagerInfo + { + virtual IVfnPtr *FindVfnPtr(void *vfnptr) = 0; + + virtual void SetInfo(int vtbloffs, int vtblidx, const char *proto) = 0; + virtual void SetHookfuncVfnptr(void *hookfunc_vfnptr) = 0; + + // Added 23.12.2005 (yup! I'm coding RIGHT BEFORE CHRISTMAS!) + // If the hookman doesn't set this, it defaults 0 + // SourceHook prefers hookmans with higher version numbers + virtual void SetVersion(int version) = 0; + }; + + class AutoHookIter + { + IHookList *m_pList; + IHookList::IIter *m_pIter; + public: + AutoHookIter(IHookList *pList) + : m_pList(pList), m_pIter(pList->GetIter()) + { + } + + ~AutoHookIter() + { + if (m_pList) + m_pList->ReleaseIter(m_pIter); + } + + bool End() + { + return m_pIter->End(); + } + + void Next() + { + m_pIter->Next(); + } + + ISHDelegate *Handler() + { + return m_pIter->Handler(); + } + + int ThisPtrOffs() + { + return m_pIter->ThisPtrOffs(); + } + + void SetToZero() + { + m_pList = 0; + } + }; + + template struct DeprecatedCallClass + { + virtual B *GetThisPtr() = 0; + virtual void *GetOrigFunc(int vtbloffs, int vtblidx) = 0; + }; + + // 09.08.2008 (6 AM, I just woke up, the others are still sleeping so i finally can use this notebook !!) + // - Today is an important day. + // I'm adding support for functions which return references. + + // How it works: + // SH_SETUPCALLS doesn't use plain rettype to store the temporary return values (plugin ret, orig ret, + // override ret) anymore; instead, it uses SourceHook::ReferenceCarrier::type + // this is typedefed to the original rettype normally, but if the rettype is a reference, it's a special class + // which stores the reference as a pointer, and implements constructors, operator= and a conversion operator. + // special cases were needed for getoverrideret / getorigret; these are implemented through the + // SourceHook::MacroRefHelpers structs. + // Furthermore, SetOverrideRet had to be changed a bit; see SourceHook::OverrideFunctor somewhere down in this file. + template struct ReferenceCarrier + { + typedef T type; + }; + + template struct ReferenceCarrier + { + class type + { + T *m_StoredRef; + public: + type() : m_StoredRef(NULL) + { + } + type(T& ref) : m_StoredRef(&ref) + { + } + + T& operator= (T& ref) + { + m_StoredRef = &ref; + return ref; + } + + operator T& () const + { + return *m_StoredRef; + } + }; + }; + + /** + * @brief The main SourceHook interface + */ + class ISourceHook + { + public: + /** + * @brief Return interface version + */ + virtual int GetIfaceVersion() = 0; + + /** + * @brief Return implementation version + */ + virtual int GetImplVersion() = 0; + + /** + * @brief Add a hook. + * + * @return True if the function succeeded, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param iface The interface pointer + * @param ifacesize The size of the class iface points to + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + virtual bool AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, + ISHDelegate *handler, bool post) = 0; + + /** + * @brief Removes a hook. + * + * @return True if the function succeeded, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param iface The interface pointer + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + virtual bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, + ISHDelegate *handler, bool post) = 0; + + /** + * @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins + * + * @param plug The unique identifier of the plugin in question + */ + virtual bool IsPluginInUse(Plugin plug) = 0; + + /** + * @brief Return a pointer to a callclass. Generate a new one if required. + * + * @param iface The interface pointer + * @param size Size of the class instance + */ + virtual DeprecatedCallClass *GetCallClass(void *iface, size_t size) = 0; + + /** + * @brief Release a callclass + * + * @param ptr Pointer to the callclass + */ + virtual void ReleaseCallClass(DeprecatedCallClass *ptr) = 0; + + virtual void SetRes(META_RES res) = 0; //!< Sets the meta result + virtual META_RES GetPrevRes() = 0; //!< Gets the meta result of the + //!< previously calledhandler + virtual META_RES GetStatus() = 0; //!< Gets the highest meta result + virtual const void *GetOrigRet() = 0; //!< Gets the original result. + //!< If not in post function, undefined + virtual const void *GetOverrideRet() = 0; //!< Gets the override result. + //!< If none is specified, NULL + virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer + ////////////////////////////////////////////////////////////////////////// + // For hook managers + virtual void HookLoopBegin(IIface *pIface) = 0; //!< Should be called when a hook loop begins + virtual void HookLoopEnd() = 0; //!< Should be called when a hook loop exits + virtual void SetCurResPtr(META_RES *mres) = 0; //!< Sets pointer to the current meta result + virtual void SetPrevResPtr(META_RES *mres) = 0; //!< Sets pointer to previous meta result + virtual void SetStatusPtr(META_RES *mres) = 0; //!< Sets pointer to the status variable + virtual void SetIfacePtrPtr(void **pp) = 0; //!< Sets pointer to the interface this pointer + virtual void SetOrigRetPtr(const void *ptr) = 0; //!< Sets the original return pointer + virtual void SetOverrideRetPtr(void *ptr) = 0; //!< Sets the override result pointer + virtual bool ShouldContinue() = 0; //!< Returns false if the hook loop should exit + + /** + * @brief Remove a hook manager. Auto-removes all hooks attached to it from plugin plug. + * + * @param plug The owner of the hook manager + * @param pubFunc The hook manager's info function + */ + virtual void RemoveHookManager(Plugin plug, HookManagerPubFunc pubFunc) = 0; + + virtual void DoRecall() = 0; //!< Initiates a recall sequence + /* + HOW RECALLS WORK: + + The problem: + Users want the ability to change parameters of the called function + from inside their handler. + The solution: + 1) Mark as "recall" + 2) Recall the function + 3) => SH's hook func gets called: + 4) The first iterator points at the first hook the last hookfunc didn't execute yet + 5) does all iteration and returns normally + 6) The user's handler returns immediately + 7) The hook func returns immediately as well + + Also note that the recalled hookfunc starts with the status the recalling hookfunc + ended with. The last handler (doing the recall) is also able to specify its own + META_RES. + */ + + virtual void *GetOverrideRetPtr() = 0; //!< Returns the pointer set by SetOverrideRetPtr + + /** + * @brief Set up the hook loop. Equivalent to calling: + * SetStatusPtr, SetPrevResPtr, SetCurResPtr, SetIfacePtrPtr, SetOrigRetPtr, Get/SetOverrideRetPtr + * + * @param statusPtr pointer to status variable + * @param prevResPtr pointer to previous result variable + * @param curResPtr pointer to current result variable + * @param ifacePtrPtr pointer to interface this pointer variable + * @param origRetPr pointer to original return value variable. NULL for void funcs + * @param overrideRetPtr pointer to override return value variable. NULL for void funcs + * + * @return Override Return Pointer the hookfunc should use (may differ from overrideRetPtr + * when the hook func is being called as part of a recall + */ + virtual void *SetupHookLoop(META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr, + void **ifacePtrPtr, const void *origRetPtr, void *overrideRetPtr) = 0; + + /** + * @brief Modes for the new AddHook + */ + enum AddHookMode + { + Hook_Normal, + Hook_VP, + Hook_DVP + }; + + /** + * @brief Add a (VP) hook. + * + * @return non-zero hook id on success, 0 otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param mode Can be either Hook_Normal or Hook_VP (vtable-wide hook) + * @param iface The interface pointer + * @param ifacesize The size of the class iface points to + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + virtual int AddHookNew(Plugin plug, AddHookMode mode, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, + ISHDelegate *handler, bool post) = 0; + + /** + * @brief Remove a VP hook by ID. + * + * @return true on success, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param hookid The hook id (returned by AddHookNew) + */ + virtual bool RemoveHookByID(Plugin plug, int hookid) = 0; + + /** + * @brief Makes sure that hooks are going to be ignored on the next call of vfnptr + * + * @param plug The unique identifier of the plugin that calls this function + * @param vfnptr The virtual function pointer of the function in question + */ + virtual void SetIgnoreHooks(Plugin plug, void *vfnptr) = 0; + + /** + * @brief Reverses SetIgnoreHooks' effect + * + * @param plug The unique identifier of the plugin that calls this function + * @param vfnptr The virtual function pointer of the function in question + */ + virtual void ResetIgnoreHooks(Plugin plug, void *vfnptr) = 0; + + /** + * @brief Finds the original entry of a virtual function pointer + * + * @param vfnptr The virtual function pointer + * @return The original entry if the virtual function pointer has been patched; NULL otherwise. + */ + virtual void *GetOrigVfnPtrEntry(void *vfnptr) = 0; + }; + + // For META_RESULT_ORIG_RET and META_RESULT_OVERRIDE_RET: + // These have to be able to return references. If T is a reference, the pointers returned + // from the SH_GLOB_SHPTR are pointers to instances of ReferenceCarrier::type. + template struct MacroRefHelpers + { + inline static const T* GetOrigRet(ISourceHook *shptr) + { + return reinterpret_cast(shptr->GetOrigRet()); + } + inline static const T* GetOverrideRet(ISourceHook *shptr) + { + return reinterpret_cast(shptr->GetOverrideRet()); + } + }; + + template struct MacroRefHelpers + { + inline static T* GetOrigRet(ISourceHook *shptr) + { + T &ref = *reinterpret_cast::type *>(shptr->GetOrigRet()); + return &ref; + } + inline static T* GetOverrideRet(ISourceHook *shptr) + { + T &ref = *reinterpret_cast::type *>(shptr->GetOverrideRet()); + return &ref; + } + }; + + // For source-level compatibility + template struct CallClass + { + T *ptr; + + CallClass(T *p) : ptr(p) + { + } + + operator T*() + { + return ptr; + } + }; + + typedef CallClass GenericCallClass; + typedef CallClass ManualCallClass; + + template + CallClass *GetCallClass(T *p) + { + return new CallClass(p); + } + + template + void ReleaseCallClass(CallClass *p) + { + delete p; + } + + template + void *GetOrigVfnPtrEntry(X *pInstance, MFP mfp, ISourceHook *pSH) + { + SourceHook::MemFuncInfo info = {true, -1, 0, 0}; + SourceHook::GetFuncInfo(pInstance, mfp, info); + + void *vfnptr = reinterpret_cast( + *reinterpret_cast(reinterpret_cast(pInstance) + info.thisptroffs + info.vtbloffs) + info.vtblindex); + + void *origentry = pSH->GetOrigVfnPtrEntry(vfnptr); + + return origentry ? origentry : *reinterpret_cast(vfnptr); + } +} + +/************************************************************************/ +/* High level interface */ +/************************************************************************/ +#define META_RESULT_STATUS SH_GLOB_SHPTR->GetStatus() +#define META_RESULT_PREVIOUS SH_GLOB_SHPTR->GetPrevRes() +#define META_RESULT_ORIG_RET(type) *SourceHook::MacroRefHelpers::GetOrigRet(SH_GLOB_SHPTR) +#define META_RESULT_OVERRIDE_RET(type) *SourceHook::MacroRefHelpers::GetOverrideRet(SH_GLOB_SHPTR) +#define META_IFACEPTR(type) reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()) + +#define SET_META_RESULT(result) SH_GLOB_SHPTR->SetRes(result) +#define RETURN_META(result) do { SET_META_RESULT(result); return; } while(0) +#define RETURN_META_VALUE(result, value) do { SET_META_RESULT(result); return (value); } while(0) + +// If a hook on a function which returns a reference does not want to specify a return value, +// it can use this macro. +// ONLY USE THIS WITH MRES_IGNORED AND MRES_HANDLED !!! +#define RETURN_META_NOREF(result, rettype) do { SET_META_RESULT(result); return reinterpret_cast(*SH_GLOB_SHPTR); } while(0) + +// only call these from the hook handlers directly! +// :TODO: enforce it ? + +// Why take a memfuncptr instead of iface and func when we have to deduce the iface anyway now? +// Well, without it, there'd be no way to specify which overloaded version we want in _VALUE + +// SourceHook::SetOverrideRet is defined later. +#define RETURN_META_NEWPARAMS(result, memfuncptr, newparams) \ + do { \ + SET_META_RESULT(result); \ + SH_GLOB_SHPTR->DoRecall(); \ + (SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams; \ + RETURN_META(MRES_SUPERCEDE); \ + } while (0) + +#define RETURN_META_VALUE_NEWPARAMS(result, value, memfuncptr, newparams) \ + do { \ + SET_META_RESULT(result); \ + SH_GLOB_SHPTR->DoRecall(); \ + if ((result) >= MRES_OVERRIDE) \ + { \ + /* meh, set the override result here because we don't get a chance to return */ \ + /* before continuing the hook loop through the recall */ \ + SourceHook::SetOverrideResult(memfuncptr)(SH_GLOB_SHPTR, value); \ + } \ + RETURN_META_VALUE(MRES_SUPERCEDE, \ + (SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams); \ + } while (0) + +// :TODO: thisptroffs in MNEWPARAMS ?? + +#if SH_COMP == SH_COMP_MSVC + +#define SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname) \ + union \ + { \ + SH_MFHCls(hookname)::ECMFP mfp; \ + void *addr; \ + } u; \ + SourceHook::EmptyClass *thisptr = reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()); \ + u.addr = (*reinterpret_cast(reinterpret_cast(thisptr) + SH_MFHCls(hookname)::ms_MFI.vtbloffs))[ \ + SH_MFHCls(hookname)::ms_MFI.vtblindex]; + +#elif SH_COMP == SH_COMP_GCC + +#define SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname) \ + union \ + { \ + SH_MFHCls(hookname)::ECMFP mfp; \ + struct \ + { \ + void *addr; \ + intptr_t adjustor; \ + } s; \ + } u; \ + SourceHook::EmptyClass *thisptr = reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()); \ + u.s.addr = (*reinterpret_cast(reinterpret_cast(thisptr) + SH_MFHCls(hookname)::ms_MFI.vtbloffs))[ \ + SH_MFHCls(hookname)::ms_MFI.vtblindex]; \ + u.s.adjustor = 0; + +#endif + +#define RETURN_META_MNEWPARAMS(result, hookname, newparams) \ + do { \ + SET_META_RESULT(result); \ + SH_GLOB_SHPTR->DoRecall(); \ + SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname); \ + (thisptr->*(u.mfp)) newparams; \ + RETURN_META(MRES_SUPERCEDE); \ + } while (0) + +#define RETURN_META_VALUE_MNEWPARAMS(result, value, hookname, newparams) \ + do { \ + SET_META_RESULT(result); \ + SH_GLOB_SHPTR->DoRecall(); \ + if ((result) >= MRES_OVERRIDE) \ + { \ + /* see RETURN_META_VALUE_NEWPARAMS */ \ + SourceHook::SetOverrideResult(SH_GLOB_SHPTR, value); \ + } \ + SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname); \ + RETURN_META_VALUE(MRES_SUPERCEDE, (thisptr->*(u.mfp)) newparams); \ + } while (0) + +#define SH_MANUALHOOK_RECONFIGURE(hookname, pvtblindex, pvtbloffs, pthisptroffs) \ + do { \ + SH_GLOB_SHPTR->RemoveHookManager(SH_GLOB_PLUGPTR, SH_MFHCls(hookname)::HookManPubFunc); \ + SH_MFHCls(hookname)::ms_MFI.thisptroffs = pthisptroffs; \ + SH_MFHCls(hookname)::ms_MFI.vtblindex = pvtblindex; \ + SH_MFHCls(hookname)::ms_MFI.vtbloffs = pvtbloffs; \ + } while (0) + + +#define SH_GET_ORIG_VFNPTR_ENTRY(inst, mfp) (SourceHook::GetOrigVfnPtrEntry(inst, mfp, SH_GLOB_SHPTR)) + +// For source-level compatibility + +#define SH_GET_CALLCLASS(ptr) SourceHook::GetCallClass(ptr) +#define SH_GET_MCALLCLASS(ptr, size) SourceHook::GetCallClass(reinterpret_cast(ptr)) +#define SH_RELEASE_CALLCLASS(ptr) SourceHook::ReleaseCallClass(ptr) + +// New ADD / REMOVE macros. +#define SH_STATIC(func) fastdelegate::MakeDelegate(func) +#define SH_MEMBER(inst, func) fastdelegate::MakeDelegate(inst, func) + +#define SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ + __SourceHook_FHAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ + post, handler) + +#define SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ + __SourceHook_FHRemove##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ + post, handler) + +#define SH_ADD_MANUALHOOK(hookname, ifaceptr, handler, post) \ + __SourceHook_FHMAdd##hookname(reinterpret_cast(ifaceptr), post, handler) + +#define SH_REMOVE_MANUALHOOK(hookname, ifaceptr, handler, post) \ + __SourceHook_FHMRemove##hookname(reinterpret_cast(ifaceptr), post, handler) + +#define SH_ADD_VPHOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ + __SourceHook_FHVPAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ + post, handler, false) + +#define SH_ADD_DVPHOOK(ifacetype, ifacefunc, vtableptr, handler, post) \ + __SourceHook_FHVPAdd##ifacetype##ifacefunc(reinterpret_cast(vtableptr), \ + post, handler, true) + +#define SH_ADD_MANUALVPHOOK(hookname, ifaceptr, handler, post) \ + __SourceHook_FHMVPAdd##hookname(reinterpret_cast(ifaceptr), post, handler, false) + +#define SH_ADD_MANUALDVPHOOK(hookname, vtableptr, handler, post) \ + __SourceHook_FHMVPAdd##hookname(reinterpret_cast(vtableptr), post, handler, true) + +#define SH_REMOVE_HOOK_ID(hookid) \ + (SH_GLOB_SHPTR->RemoveHookByID(SH_GLOB_PLUGPTR, hookid)) + +// Old macros +// !! These are now deprecated. Instead, use one of these: +// SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) +// SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(inst, func), post) + +#define SH_ADD_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \ + SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) +#define SH_ADD_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \ + SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) + +// SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) +// SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(inst, func), post) + +#define SH_REMOVE_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \ + SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) +#define SH_REMOVE_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \ + SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) + +// SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) +// SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(inst, func), post) + +#define SH_ADD_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \ + SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) +#define SH_ADD_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \ + SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) + +// SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) +// SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(inst, func), post) + +#define SH_REMOVE_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \ + SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) +#define SH_REMOVE_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \ + SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) + +#define SH_NOATTRIB + + + + +#if SH_COMP == SH_COMP_MSVC +# define SH_SETUP_MFP(mfp) \ + reinterpret_cast(&mfp)[0] = vfnptr_origentry; +#elif SH_COMP == SH_COMP_GCC +# define SH_SETUP_MFP(mfp) \ + reinterpret_cast(&mfp)[0] = vfnptr_origentry; \ + reinterpret_cast(&mfp)[1] = 0; +#else +# error Not supported yet. +#endif + +////////////////////////////////////////////////////////////////////////// +#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov +#define SH_MFHCls(hookname) __SourceHook_MFHCls_##hookname + +#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \ + SH_FHCls(ifacetype,ifacefunc,overload)() \ + { \ + GetFuncInfo(funcptr, ms_MFI); \ + } \ + \ + static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::IHookManagerInfo *param) \ + { \ + using namespace ::SourceHook; \ + GetFuncInfo(funcptr, ms_MFI); \ + /* Verify interface version */ \ + if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \ + return 1; \ + if (SH_GLOB_SHPTR->GetImplVersion() < SH_IMPL_VERSION) \ + return 1; \ + \ + if (action == HA_GetInfo) \ + { \ + param->SetVersion(SH_HOOKMAN_VERSION); \ + param->SetInfo(ms_MFI.vtbloffs, ms_MFI.vtblindex, \ + reinterpret_cast(&ms_Proto)); \ + \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \ + param->SetHookfuncVfnptr( \ + reinterpret_cast(reinterpret_cast(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]); \ + return 0; \ + } \ + else if (action == HA_Register) \ + { \ + ms_HI = param; \ + return 0; \ + } \ + else if (action == HA_Unregister) \ + { \ + ms_HI = NULL; \ + return 0; \ + } \ + else \ + return 1; \ + } + +// It has to be possible to use the macros in namespaces +// -> So we need to access and extend the global SourceHook namespace +// We use a namespace alias for this +#define SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, funcptr) \ + struct SH_FHCls(ifacetype,ifacefunc,overload) \ + { \ + static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \ + static ::SourceHook::MemFuncInfo ms_MFI; \ + static ::SourceHook::IHookManagerInfo *ms_HI; \ + static ::SourceHook::ProtoInfo ms_Proto; \ + SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) + +#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, funcptr) \ + }; \ + SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \ + ::SourceHook::MemFuncInfo SH_FHCls(ifacetype,ifacefunc,overload)::ms_MFI; \ + ::SourceHook::IHookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \ + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \ + SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ + { \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0 || !mfi.isVirtual) \ + return false; /* No non-virtual functions / virtual inheritance supported */ \ + \ + return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, ::SourceHook::ISourceHook::Hook_Normal, iface, mfi.thisptroffs, \ + SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, \ + new CSHDelegate(handler), post); \ + } \ + int __SourceHook_FHVPAdd##ifacetype##ifacefunc(void *iface, bool post, \ + SH_FHCls(ifacetype,ifacefunc,overload)::FD handler, bool direct) \ + { \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0 || !mfi.isVirtual) \ + return false; /* No non-virtual functions / virtual inheritance supported */ \ + \ + return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, \ + direct ? ::SourceHook::ISourceHook::Hook_DVP : ::SourceHook::ISourceHook::Hook_VP, \ + iface, mfi.thisptroffs, SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, \ + new CSHDelegate(handler), post); \ + } \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ + { \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0) \ + return false; /* No virtual inheritance supported */ \ + \ + CSHDelegate tmp(handler); \ + return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, mfi.thisptroffs, \ + SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, &tmp, post); \ + } \ + +#define SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, pvtbloffs, pvtblidx, pthisptroffs) \ + struct SH_MFHCls(hookname) \ + { \ + static SH_MFHCls(hookname) ms_Inst; \ + static ::SourceHook::MemFuncInfo ms_MFI; \ + static ::SourceHook::IHookManagerInfo *ms_HI; \ + static ::SourceHook::ProtoInfo ms_Proto; \ + \ + SH_MFHCls(hookname)() \ + { \ + ms_MFI.isVirtual = true; \ + ms_MFI.thisptroffs = pthisptroffs; \ + ms_MFI.vtblindex = pvtblidx; \ + ms_MFI.vtbloffs = pvtbloffs; \ + } \ + static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::IHookManagerInfo *param) \ + { \ + using namespace ::SourceHook; \ + /* we don't set ms_MFI here because manual hookmans can be reconfigured */ \ + /* :FIXME: possible problem: someone adding a hook from a constructor of a global entity */ \ + /* which is construced before SH_MFHCls(hookname)() gets called? */ \ + /* Verify interface version */ \ + if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \ + return 1; \ + if (SH_GLOB_SHPTR->GetImplVersion() < SH_IMPL_VERSION) \ + return 1; \ + \ + if (action == HA_GetInfo) \ + { \ + param->SetVersion(SH_HOOKMAN_VERSION); \ + param->SetInfo(ms_MFI.vtbloffs, ms_MFI.vtblindex, \ + reinterpret_cast(&ms_Proto)); \ + \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(&SH_MFHCls(hookname)::Func, mfi); \ + param->SetHookfuncVfnptr( \ + reinterpret_cast(reinterpret_cast(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]); \ + return 0; \ + } \ + else if (action == HA_Register) \ + { \ + ms_HI = param; \ + return 0; \ + } \ + else if (action == HA_Unregister) \ + { \ + ms_HI = NULL; \ + return 0; \ + } \ + else \ + return 1; \ + } + +#define SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, pvtbloffs, pvtblidx, pthisptroffs) \ + }; \ + SH_MFHCls(hookname) SH_MFHCls(hookname)::ms_Inst; \ + ::SourceHook::MemFuncInfo SH_MFHCls(hookname)::ms_MFI; \ + ::SourceHook::IHookManagerInfo *SH_MFHCls(hookname)::ms_HI; \ + int __SourceHook_FHMAdd##hookname(void *iface, bool post, \ + SH_MFHCls(hookname)::FD handler) \ + { \ + return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, ::SourceHook::ISourceHook::Hook_Normal, iface, pthisptroffs, \ + SH_MFHCls(hookname)::HookManPubFunc, \ + new ::SourceHook::CSHDelegate(handler), post); \ + } \ + int __SourceHook_FHMVPAdd##hookname(void *iface, bool post, \ + SH_MFHCls(hookname)::FD handler, bool direct) \ + { \ + return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, \ + direct ? ::SourceHook::ISourceHook::Hook_DVP : ::SourceHook::ISourceHook::Hook_VP, \ + iface, pthisptroffs, SH_MFHCls(hookname)::HookManPubFunc, \ + new ::SourceHook::CSHDelegate(handler), post); \ + } \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + SH_MFHCls(hookname)::FD handler) \ + { \ + ::SourceHook::CSHDelegate tmp(handler); \ + return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, pthisptroffs, \ + SH_MFHCls(hookname)::HookManPubFunc, &tmp, post); \ + } \ + + +#define SH_SETUPCALLS(rettype, paramtypes, params) \ + /* 1) Find the vfnptr */ \ + using namespace ::SourceHook; \ + void *ourvfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \ + IVfnPtr *vfnptr = ms_HI->FindVfnPtr(ourvfnptr); \ + SH_ASSERT(vfnptr, ("Called with vfnptr 0x%p which couldn't be found in the list", ourvfnptr)); \ + \ + void *vfnptr_origentry = vfnptr->GetOrigEntry(); \ + /* ... and the iface */ \ + IIface *ifinfo = vfnptr->FindIface(reinterpret_cast(this)); \ + if (!ifinfo) \ + { \ + /* The iface info was not found. Redirect the call to the original function. */ \ + rettype (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + return (reinterpret_cast(this)->*mfp)params; \ + } \ + /* 2) Declare some vars and set it up */ \ + SH_GLOB_SHPTR->HookLoopBegin(ifinfo); \ + IHookList *prelist = ifinfo->GetPreHooks(); \ + IHookList *postlist = ifinfo->GetPostHooks(); \ + META_RES status = MRES_IGNORED; \ + META_RES prev_res; \ + META_RES cur_res; \ + typedef ReferenceCarrier::type my_rettype; \ + my_rettype orig_ret; \ + my_rettype override_ret; \ + my_rettype plugin_ret; \ + void* ifptr; \ + my_rettype *pOverrideRet = reinterpret_cast(SH_GLOB_SHPTR->SetupHookLoop( \ + &status, &prev_res, &cur_res, &ifptr, &orig_ret, &override_ret)); + +#define SH_CALL_HOOKS(post, params) \ + if (SH_GLOB_SHPTR->ShouldContinue()) \ + { \ + prev_res = MRES_IGNORED; \ + for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \ + { \ + cur_res = MRES_IGNORED; \ + ifptr = reinterpret_cast(reinterpret_cast(this) - iter.ThisPtrOffs()); \ + plugin_ret = reinterpret_cast*>(iter.Handler())->GetDeleg() params; \ + prev_res = cur_res; \ + if (cur_res > status) \ + status = cur_res; \ + if (cur_res >= MRES_OVERRIDE) \ + *pOverrideRet = plugin_ret; \ + if (!SH_GLOB_SHPTR->ShouldContinue()) \ + { \ + iter.SetToZero(); \ + break; \ + } \ + } \ + } + +#define SH_CALL_ORIG(rettype, paramtypes, params) \ + if (status != MRES_SUPERCEDE) \ + { \ + rettype (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + orig_ret = (reinterpret_cast(this)->*mfp)params; \ + } \ + else \ + orig_ret = override_ret; \ + +#define SH_RETURN() \ + SH_GLOB_SHPTR->HookLoopEnd(); \ + return status >= MRES_OVERRIDE ? *pOverrideRet : orig_ret; + +#define SH_HANDLEFUNC(paramtypes, params, rettype) \ + SH_SETUPCALLS(rettype, paramtypes, params) \ + SH_CALL_HOOKS(pre, params) \ + SH_CALL_ORIG(rettype, paramtypes, params) \ + SH_CALL_HOOKS(post, params) \ + SH_RETURN() + +////////////////////////////////////////////////////////////////////////// +#define SH_SETUPCALLS_void(paramtypes, params) \ + /* 1) Find the vfnptr */ \ + using namespace ::SourceHook; \ + void *ourvfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \ + IVfnPtr *vfnptr = ms_HI->FindVfnPtr(ourvfnptr); \ + SH_ASSERT(vfnptr, ("Called with vfnptr 0x%p which couldn't be found in the list", ourvfnptr)); \ + \ + void *vfnptr_origentry = vfnptr->GetOrigEntry(); \ + /* ... and the iface */ \ + IIface *ifinfo = vfnptr->FindIface(reinterpret_cast(this)); \ + if (!ifinfo) \ + { \ + /* The iface info was not found. Redirect the call to the original function. */ \ + void (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + (reinterpret_cast(this)->*mfp)params; \ + return; \ + } \ + /* 2) Declare some vars and set it up */ \ + SH_GLOB_SHPTR->HookLoopBegin(ifinfo); \ + IHookList *prelist = ifinfo->GetPreHooks(); \ + IHookList *postlist = ifinfo->GetPostHooks(); \ + META_RES status = MRES_IGNORED; \ + META_RES prev_res; \ + META_RES cur_res; \ + void* ifptr; \ + SH_GLOB_SHPTR->SetupHookLoop(&status, &prev_res, &cur_res, &ifptr, NULL, NULL); \ + +#define SH_CALL_HOOKS_void(post, params) \ + if (SH_GLOB_SHPTR->ShouldContinue()) \ + { \ + prev_res = MRES_IGNORED; \ + for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \ + { \ + cur_res = MRES_IGNORED; \ + ifptr = reinterpret_cast(reinterpret_cast(this) - iter.ThisPtrOffs()); \ + reinterpret_cast*>(iter.Handler())->GetDeleg() params; \ + prev_res = cur_res; \ + if (cur_res > status) \ + status = cur_res; \ + if (!SH_GLOB_SHPTR->ShouldContinue()) \ + { \ + iter.SetToZero(); \ + break; \ + } \ + } \ + } + +#define SH_CALL_ORIG_void(paramtypes, params) \ + if (status != MRES_SUPERCEDE) \ + { \ + void (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + (reinterpret_cast(this)->*mfp)params; \ + } + +#define SH_RETURN_void() \ + SH_GLOB_SHPTR->HookLoopEnd(); + +#define SH_HANDLEFUNC_void(paramtypes, params) \ + SH_SETUPCALLS_void(paramtypes, params) \ + SH_CALL_HOOKS_void(pre, params) \ + SH_CALL_ORIG_void(paramtypes, params) \ + SH_CALL_HOOKS_void(post, params) \ + SH_RETURN_void() + + +// Special vafmt handlers +// :TODO: what +#define SH_HANDLEFUNC_vafmt(paramtypes, params_orig, params_plug, rettype) \ + SH_SETUPCALLS(rettype, paramtypes, params_orig) \ + SH_CALL_HOOKS(pre, params_plug) \ + SH_CALL_ORIG(rettype, paramtypes, params_orig) \ + SH_CALL_HOOKS(post, params_plug) \ + SH_RETURN() + +#define SH_HANDLEFUNC_void_vafmt(paramtypes, params_orig, params_plug) \ + SH_SETUPCALLS_void(paramtypes, params_orig) \ + SH_CALL_HOOKS_void(pre, params_plug) \ + SH_CALL_ORIG_void(paramtypes, params_orig) \ + SH_CALL_HOOKS_void(post, params_plug) \ + SH_RETURN_void() + +////////////////////////////////////////////////////////////////////////// + +// :FIXME: +// sizeof on references returns the size of the datatype, NOT the pointer size or something +// -> one should probably flag references in __SourceHook_ParamSizes_* ! +// or simply assume that their size is sizeof(void*)=SH_PTRSIZE... could be doable through a simple template + + +// ********* Support for 0 arguments ********* +#define SH_DECL_HOOK0(ifacetype, ifacefunc, attr, overload, rettype) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate0 FD; \ + virtual rettype Func() \ + { SH_HANDLEFUNC((), (), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0 }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 0, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK0_void(ifacetype, ifacefunc, attr, overload) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate0<> FD; \ + virtual void Func() \ + { SH_HANDLEFUNC_void((), ()); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0 }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 0, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK0_vafmt(ifacetype, ifacefunc, attr, overload, rettype) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate1 FD; \ + virtual rettype Func(const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((...), ("%s", buf), (buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1 }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 0, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK0_void_vafmt(ifacetype, ifacefunc, attr, overload) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate1 FD; \ + virtual void Func(const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((...), ("%s", buf), (buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1 }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 0, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK0(hookname, vtblidx, vtbloffs, thisptroffs, rettype) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate0 FD; \ + virtual rettype Func() \ + { SH_HANDLEFUNC((), (), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0 }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 0, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK0_void(hookname, vtblidx, vtbloffs, thisptroffs) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate0<> FD; \ + virtual void Func() \ + { SH_HANDLEFUNC_void((), ()); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0 }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 0, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 1 arguments ********* +#define SH_DECL_HOOK1(ifacetype, ifacefunc, attr, overload, rettype, param1) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate1 FD; \ + virtual rettype Func(param1 p1) \ + { SH_HANDLEFUNC((param1), (p1), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 1, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK1_void(ifacetype, ifacefunc, attr, overload, param1) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate1 FD; \ + virtual void Func(param1 p1) \ + { SH_HANDLEFUNC_void((param1), (p1)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 1, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK1_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate2 FD; \ + virtual rettype Func(param1 p1, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, ...), (p1, "%s", buf), (p1, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 1, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK1_void_vafmt(ifacetype, ifacefunc, attr, overload, param1) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate2 FD; \ + virtual void Func(param1 p1, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, ...), (p1, "%s", buf), (p1, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 1, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK1(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate1 FD; \ + virtual rettype Func(param1 p1) \ + { SH_HANDLEFUNC((param1), (p1), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 1, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK1_void(hookname, vtblidx, vtbloffs, thisptroffs, param1) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate1 FD; \ + virtual void Func(param1 p1) \ + { SH_HANDLEFUNC_void((param1), (p1)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 1, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 2 arguments ********* +#define SH_DECL_HOOK2(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate2 FD; \ + virtual rettype Func(param1 p1, param2 p2) \ + { SH_HANDLEFUNC((param1, param2), (p1, p2), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 2, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK2_void(ifacetype, ifacefunc, attr, overload, param1, param2) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate2 FD; \ + virtual void Func(param1 p1, param2 p2) \ + { SH_HANDLEFUNC_void((param1, param2), (p1, p2)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 2, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK2_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate3 FD; \ + virtual rettype Func(param1 p1, param2 p2, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, ...), (p1, p2, "%s", buf), (p1, p2, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 2, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK2_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate3 FD; \ + virtual void Func(param1 p1, param2 p2, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, ...), (p1, p2, "%s", buf), (p1, p2, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 2, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK2(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate2 FD; \ + virtual rettype Func(param1 p1, param2 p2) \ + { SH_HANDLEFUNC((param1, param2), (p1, p2), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 2, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK2_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate2 FD; \ + virtual void Func(param1 p1, param2 p2) \ + { SH_HANDLEFUNC_void((param1, param2), (p1, p2)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 2, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 3 arguments ********* +#define SH_DECL_HOOK3(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate3 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3) \ + { SH_HANDLEFUNC((param1, param2, param3), (p1, p2, p3), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 3, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK3_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate3 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3) \ + { SH_HANDLEFUNC_void((param1, param2, param3), (p1, p2, p3)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 3, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK3_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate4 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, ...), (p1, p2, p3, "%s", buf), (p1, p2, p3, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 3, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK3_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate4 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, ...), (p1, p2, p3, "%s", buf), (p1, p2, p3, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 3, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK3(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate3 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3) \ + { SH_HANDLEFUNC((param1, param2, param3), (p1, p2, p3), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 3, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK3_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate3 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3) \ + { SH_HANDLEFUNC_void((param1, param2, param3), (p1, p2, p3)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 3, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 4 arguments ********* +#define SH_DECL_HOOK4(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate4 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4) \ + { SH_HANDLEFUNC((param1, param2, param3, param4), (p1, p2, p3, p4), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 4, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK4_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate4 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4), (p1, p2, p3, p4)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 4, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK4_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate5 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, ...), (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 4, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK4_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate5 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, ...), (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 4, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK4(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate4 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4) \ + { SH_HANDLEFUNC((param1, param2, param3, param4), (p1, p2, p3, p4), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 4, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK4_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate4 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4), (p1, p2, p3, p4)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 4, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 5 arguments ********* +#define SH_DECL_HOOK5(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate5 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 5, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK5_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate5 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 5, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK5_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate6 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, ...), (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 5, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK5_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate6 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, ...), (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 5, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK5(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate5 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 5, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK5_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate5 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 5, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 6 arguments ********* +#define SH_DECL_HOOK6(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate6 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 6, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK6_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate6 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 6, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK6_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate7 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, ...), (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 6, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK6_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate7 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, ...), (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 6, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK6(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate6 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 6, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK6_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate6 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 6, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 7 arguments ********* +#define SH_DECL_HOOK7(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate7 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 7, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK7_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate7 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 7, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK7_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate8 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, ...), (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 7, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK7_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate8 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, ...), (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 7, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK7(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate7 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 7, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK7_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate7 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 7, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 8 arguments ********* +#define SH_DECL_HOOK8(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate8 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 8, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK8_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate8 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 8, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK8_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate9 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, ...), (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 8, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK8_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate9 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, ...), (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 8, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK8(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate8 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 8, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK8_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate8 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 8, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 9 arguments ********* +#define SH_DECL_HOOK9(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate9 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 9, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK9_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate9 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 9, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK9_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate10 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 9, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK9_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate10 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 9, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK9(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate9 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 9, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK9_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate9 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 9, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 10 arguments ********* +#define SH_DECL_HOOK10(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate10 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 10, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK10_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate10 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 10, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK10_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate11 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 10, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK10_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate11 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 10, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK10(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate10 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 10, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK10_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate10 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 10, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 11 arguments ********* +#define SH_DECL_HOOK11(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate11 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 11, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK11_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate11 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 11, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK11_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate12 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 11, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK11_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate12 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 11, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK11(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate11 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 11, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK11_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate11 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 11, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 12 arguments ********* +#define SH_DECL_HOOK12(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate12 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 12, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK12_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate12 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 12, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK12_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate13 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 12, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK12_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate13 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 12, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK12(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate12 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 12, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK12_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate12 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 12, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 13 arguments ********* +#define SH_DECL_HOOK13(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate13 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 13, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK13_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate13 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 13, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK13_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate14 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 13, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK13_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate14 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 13, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK13(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate13 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 13, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK13_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate13 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 13, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 14 arguments ********* +#define SH_DECL_HOOK14(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate14 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 14, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK14_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate14 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 14, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK14_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate15 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 14, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK14_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate15 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 14, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK14(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate14 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 14, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK14_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate14 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 14, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 15 arguments ********* +#define SH_DECL_HOOK15(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate15 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 15, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK15_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate15 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 15, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK15_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate16 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 15, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK15_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate16 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 15, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK15(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate15 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 15, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK15_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate15 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 15, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 16 arguments ********* +#define SH_DECL_HOOK16(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate16 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 16, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK16_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate16 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 16, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK16_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate17 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 16, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK16_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate17 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 16, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK16(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate16 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 16, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK16_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate16 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 16, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 17 arguments ********* +#define SH_DECL_HOOK17(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate17 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 17, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK17_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate17 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 17, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK17_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate18 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 17, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK17_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate18 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 17, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK17(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate17 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 17, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK17_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate17 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 17, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 18 arguments ********* +#define SH_DECL_HOOK18(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate18 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 18, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK18_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate18 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 18, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK18_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate19 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 18, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK18_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate19 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 18, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK18(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate18 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 18, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK18_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate18 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 18, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 19 arguments ********* +#define SH_DECL_HOOK19(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate19 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 19, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK19_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate19 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 19, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK19_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate20 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 19, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK19_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate20 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 19, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK19(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate19 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 19, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK19_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate19 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 19, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 20 arguments ********* +#define SH_DECL_HOOK20(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate20 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19), sizeof(param20) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 20, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK20_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate20 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19), sizeof(param20) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 20, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK20_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate21 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19), sizeof(param20) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 20, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK20_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate21 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19), sizeof(param20) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 20, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK20(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate20 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19), sizeof(param20) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 20, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK20_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate20 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19), sizeof(param20) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 20, __SourceHook_ParamSizesM_##hookname); \ + + + + +////////////////////////////////////////////////////////////////////////// +// SH_CALL + +#define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \ +{ \ + using namespace ::SourceHook; \ + \ + m_pSH->SetIgnoreHooks(m_Plug, m_VfnPtr); \ + RetType tmpret = (m_ThisPtr->*m_MFP)call; \ + m_pSH->ResetIgnoreHooks(m_Plug, m_VfnPtr); \ + return tmpret; \ +} + +#define SH_MAKE_EXECUTABLECLASS_OB_void(call, prms) \ +{ \ + using namespace ::SourceHook; \ + \ + m_pSH->SetIgnoreHooks(m_Plug, m_VfnPtr); \ + (m_ThisPtr->*m_MFP)call; \ + m_pSH->ResetIgnoreHooks(m_Plug, m_VfnPtr); \ +} + +namespace SourceHook +{ + // Call Class Wrapper! + template struct CCW + { + typedef T type; + + // Get Real Pointer! + static inline T *GRP(T *p) + { + return p; + } + }; + + template struct CCW< CallClass > + { + typedef T type; + + // Get Real Pointer! + static inline T *GRP(CallClass *p) + { + return p->ptr; + } + }; + + + // Support for 0 arguments + template class ExecutableClass0 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass0(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()() const + SH_MAKE_EXECUTABLECLASS_OB((), ()) + + + template RetType operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB((p1), (Param1)) + + template RetType operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2), (Param1, Param2)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3), (Param1, Param2, Param3)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass0 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass0(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()() const + SH_MAKE_EXECUTABLECLASS_OB_void((), ()) + + + template void operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1), (Param1)) + + template void operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2), (Param1, Param2)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3), (Param1, Param2, Param3)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 1 arguments + template class ExecutableClass1 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass1(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB((p1), (Param1)) + + + template RetType operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2), (Param1, Param2)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3), (Param1, Param2, Param3)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass1 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass1(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1), (Param1)) + + + template void operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2), (Param1, Param2)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3), (Param1, Param2, Param3)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 2 arguments + template class ExecutableClass2 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass2(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2), (Param1, Param2)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3), (Param1, Param2, Param3)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass2 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass2(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2), (Param1, Param2)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3), (Param1, Param2, Param3)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 3 arguments + template class ExecutableClass3 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass3(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3), (Param1, Param2, Param3)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass3 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass3(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3), (Param1, Param2, Param3)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 4 arguments + template class ExecutableClass4 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass4(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass4 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass4(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 5 arguments + template class ExecutableClass5 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass5(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass5 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass5(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 6 arguments + template class ExecutableClass6 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass6(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass6 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass6(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 7 arguments + template class ExecutableClass7 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass7(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass7 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass7(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 8 arguments + template class ExecutableClass8 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass8(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass8 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass8(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 9 arguments + template class ExecutableClass9 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass9(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass9 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass9(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 10 arguments + template class ExecutableClass10 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass10(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass10 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass10(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 11 arguments + template class ExecutableClass11 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass11(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass11 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass11(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 12 arguments + template class ExecutableClass12 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass12(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass12 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass12(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 13 arguments + template class ExecutableClass13 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass13(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass13 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass13(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 14 arguments + template class ExecutableClass14 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass14(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass14 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass14(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 15 arguments + template class ExecutableClass15 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass15(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass15 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass15(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 16 arguments + template class ExecutableClass16 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass16(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass16 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass16(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 17 arguments + template class ExecutableClass17 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass17(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass17 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass17(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 18 arguments + template class ExecutableClass18 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass18(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass18 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass18(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 19 arguments + template class ExecutableClass19 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass19(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass19 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass19(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 20 arguments + template class ExecutableClass20 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass20(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + + }; + + template class ExecutableClass20 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass20(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + + }; + + +} + +#define SH__CALL_GET_VFNPTR_NORMAL \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(CCW::GRP(ptr), mfp, mfi); \ + void *vfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(CCW::GRP(ptr)) + mfi.thisptroffs + mfi.vtbloffs) + mfi.vtblindex); + +#define SH__CALL_GET_VFNPTR_MANUAL \ + using namespace ::SourceHook; \ + void *vfnptr = reinterpret_cast( \ + *reinterpret_cast( (reinterpret_cast(CCW::GRP(ptr)) + thisptroffs + vtbloffs) ) + vtblidx); \ + /* patch mfp */ \ + *reinterpret_cast(&mfp) = *reinterpret_cast(vfnptr); + +// SH_CALL needs to deduce the return type -> it uses templates and function overloading +// That's why SH_CALL takes two parameters: "mfp2" of type RetType(X::*mfp)(params), and "mfp" of type MFP +// The only purpose of the mfp2 parameter is to extract the return type + + +// Support for 0 arguments +template +SourceHook::ExecutableClass0::type, MFP, RetType> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass0::type, MFP, RetType>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass0::type, MFP, RetType> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)()const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass0::type, MFP, RetType>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass0 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass0( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 1 arguments +template +SourceHook::ExecutableClass1::type, MFP, RetType, Param1> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass1::type, MFP, RetType, Param1>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass1::type, MFP, RetType, Param1> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass1::type, MFP, RetType, Param1>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass1 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass1( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 2 arguments +template +SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass2 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass2( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 3 arguments +template +SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass3 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass3( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 4 arguments +template +SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass4 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass4( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 5 arguments +template +SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass5 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass5( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 6 arguments +template +SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass6 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass6( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 7 arguments +template +SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass7 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass7( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 8 arguments +template +SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass8 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass8( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 9 arguments +template +SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass9 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass9( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 10 arguments +template +SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass10 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass10( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 11 arguments +template +SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass11 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass11( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 12 arguments +template +SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass12 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass12( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 13 arguments +template +SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass13 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass13( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 14 arguments +template +SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass14 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass14( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 15 arguments +template +SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass15 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass15( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 16 arguments +template +SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass16 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass16( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 17 arguments +template +SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass17 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass17( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 18 arguments +template +SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass18 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass18( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 19 arguments +template +SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass19 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass19( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 20 arguments +template +SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass20 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass20( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + + +#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300 +// GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it + + +// Support for 0 arguments +template +SourceHook::ExecutableClass0::type, MFP, RetType> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass0::type, MFP, RetType>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass0::type, MFP, RetType> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass0::type, MFP, RetType>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 1 arguments +template +SourceHook::ExecutableClass1::type, MFP, RetType, Param1> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass1::type, MFP, RetType, Param1>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass1::type, MFP, RetType, Param1> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass1::type, MFP, RetType, Param1>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 2 arguments +template +SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 3 arguments +template +SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 4 arguments +template +SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 5 arguments +template +SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 6 arguments +template +SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 7 arguments +template +SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 8 arguments +template +SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 9 arguments +template +SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 10 arguments +template +SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 11 arguments +template +SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 12 arguments +template +SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 13 arguments +template +SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 14 arguments +template +SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 15 arguments +template +SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 16 arguments +template +SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 17 arguments +template +SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 18 arguments +template +SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 19 arguments +template +SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 20 arguments +template +SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + + +#endif + +#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp), SH_GLOB_SHPTR, SH_GLOB_PLUGPTR) +#define SH_MCALL2(ptr, mfp, vtblidx, vtbloffs, thisptroffs) SH_MCALL3((ptr), (mfp), (mfp), (vtblidx), (vtbloffs), (thisptroffs), SH_GLOB_SHPTR, SH_GLOB_PLUGPTR) +#define SH_MCALL(ptr, mhookname) SH_MCALL2((ptr), SH_MFHCls(mhookname)::ECMFP(), SH_MFHCls(mhookname)::ms_MFI.vtblindex, \ + SH_MFHCls(mhookname)::ms_MFI.vtbloffs, SH_MFHCls(mhookname)::ms_MFI.thisptroffs) + +#undef SH_MAKE_EXECUTABLECLASS_OB + +////////////////////////////////////////////////////////////////////////// +// SetOverrideRet and RecallGetIface for recalls +// These take a ISourceHook pointer instead of using SH_GLOB_SHPTR directly +// The reason is that the user may want to redefine SH_GLOB_SHPTR - then the macros +// (META_RETURN_VALUE_NEWPARAMS) should obey the new pointer. + +namespace SourceHook +{ + template + void SetOverrideResult(ISourceHook *shptr, const RetType res) + { + *reinterpret_cast(shptr->GetOverrideRetPtr()) = res; + } + + // SetOverrideResult used to be implemented like this: + // SetOverrideResult(shptr, memfuncptr, return); + // normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference + // (it thought it was ambigous - the ref and non-ref type) + // so now SetOverrideResult(memfuncptr) deduces the ret type, and returns a functor which does the work + // new syntax: SetOverrideResult(memfuncptr)(shptr, return) + // This also allows us to create a special version for references which respects ReferenceCarrier. + + template struct OverrideFunctor + { + void operator()(ISourceHook *shptr, T res) + { + *reinterpret_cast(shptr->GetOverrideRetPtr()) = res; + } + }; + template struct OverrideFunctor + { + void operator()(ISourceHook *shptr, T &res) + { + // overrideretptr points to ReferenceCarrier + *reinterpret_cast::type *>(shptr->GetOverrideRetPtr()) = res; + } + }; + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)()) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)()) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + +} + +#endif + // The pope is dead. -> :( diff --git a/utils/mmsource/core-legacy/sourcehook/generate/sourcehook.hxx b/utils/mmsource/core-legacy/sourcehook/generate/sourcehook.hxx new file mode 100644 index 00000000..c1852c63 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/generate/sourcehook.hxx @@ -0,0 +1,1503 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2007 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +/** +* @file sourcehook.h +* @brief Contains the public SourceHook API +*/ + +#ifndef __SOURCEHOOK_H__ +#define __SOURCEHOOK_H__ + +// Interface revisions: +// 1 - Initial revision +// 2 - Changed to virtual functions for iterators and all queries +// 3 - Added "hook loop status variable" +// 4 - Reentrant +#define SH_IFACE_VERSION 4 + +// Impl versions: +// ??? +// 4 - addition of hook ids and vp hooks (with them, AddHookNew and RemoveHookNew) +// This is not a SH_IFACE_VERSION change so that old plugins continue working! +// 5 - addition of direct vp hooks (new hook mode; from now on AddHookNew checks for +// invalid hookmode -> impl version won't have to change because of things like this) +#define SH_IMPL_VERSION 5 + +// Hookman version: +// 1 - Support for recalls, performance optimisations +#define SH_HOOKMAN_VERSION 1 + +// The value of SH_GLOB_SHPTR has to be a pointer to SourceHook::ISourceHook +// It's used in various macros +#ifndef SH_GLOB_SHPTR +#define SH_GLOB_SHPTR g_SHPtr +#endif + +// Used to identify the current plugin +#ifndef SH_GLOB_PLUGPTR +#define SH_GLOB_PLUGPTR g_PLID +#endif + +#ifdef SH_DEBUG +# include +# include + +# define SH_ASSERT(x, info) \ + do { \ + if (!(x)) \ + { \ + printf("SOURCEHOOK DEBUG ASSERTION FAILED: %s:%u(%s): %s: ", __FILE__, __LINE__, __FUNCTION__, #x); \ + printf info; \ + putchar('\n'); \ + abort(); \ + } \ + } while(0) + +#else +# define SH_ASSERT(x, info) +#endif + +// System +#define SH_SYS_WIN32 1 +#define SH_SYS_LINUX 2 + +#ifdef _WIN32 +# define SH_SYS SH_SYS_WIN32 +#elif defined __linux__ +# define SH_SYS SH_SYS_LINUX +#else +# error Unsupported system +#endif + +// Compiler +#define SH_COMP_GCC 1 +#define SH_COMP_MSVC 2 + +#ifdef _MSC_VER +# define SH_COMP SH_COMP_MSVC +#elif defined __GNUC__ +# define SH_COMP SH_COMP_GCC +#else +# error Unsupported compiler +#endif + +#if SH_COMP==SH_COMP_MSVC && _MSC_VER < 1500 +# define vsnprintf _vsnprintf +#endif + +#if SH_SYS != SH_SYS_WIN32 +# include +#endif + +#define SH_PTRSIZE sizeof(void*) + +#include "FastDelegate.h" +#include "sh_memfuncinfo.h" + +// Good old metamod! + +// Flags returned by a plugin's api function. +// NOTE: order is crucial, as greater/less comparisons are made. +enum META_RES +{ + MRES_IGNORED=0, // plugin didn't take any action + MRES_HANDLED, // plugin did something, but real function should still be called + MRES_OVERRIDE, // call real function, but use my return value + MRES_SUPERCEDE // skip real function; use my return value +}; + + +namespace SourceHook +{ + /** + * @brief Specifies the size (in bytes) for the internal buffer of vafmt(printf-like) function handlers + */ + const int STRBUF_LEN=4096; + + /** + * @brief An empty class. No inheritance used. Used for original-function-call hacks + */ + class EmptyClass + { + }; + + /** + * @brief Implicit cast. + */ + template + inline Out implicit_cast(In input) + { + return input; + } + + /** + * @brief A plugin typedef + * + * SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it and every + * plugin has a unique identifier, everything is ok. + * It should also be possible to set it to 0. + */ + typedef int Plugin; + + struct ProtoInfo + { + ProtoInfo(int rtsz, int nop, const int *p) : beginningNull(0), retTypeSize(rtsz), numOfParams(nop), params(p) + { + } + int beginningNull; //!< To distinguish from old protos (which never begin with 0) + int retTypeSize; //!< 0 if void + int numOfParams; //!< number of parameters + const int *params; //!< params[0]=0 (or -1 for vararg), params[1]=size of first param, ... + }; + + /** + * @brief Specifies the actions for hook managers + */ + enum HookManagerAction + { + HA_GetInfo = 0, //!< Store info about the hook manager + HA_Register, //!< Save the IHookManagerInfo pointer for future reference + HA_Unregister //!< Clear the saved pointer + }; + + struct IHookManagerInfo; + + /** + * @brief Pointer to hook manager interface function + * + * A "hook manager" is a the only thing that knows the actual protoype of the function at compile time. + * + * @param ha What the hook manager should do + * @param hi A pointer to IHookManagerInfo + */ + typedef int (*HookManagerPubFunc)(HookManagerAction ha, IHookManagerInfo *hi); + + class ISHDelegate + { + public: + virtual void DeleteThis() = 0; // Ugly, I know + virtual bool IsEqual(ISHDelegate *other) = 0; + }; + + template class CSHDelegate : public ISHDelegate + { + T m_Deleg; + public: + CSHDelegate(T deleg) : m_Deleg(deleg) + { + } + + CSHDelegate(const CSHDelegate &other) : m_Deleg(other.m_Deleg) + { + } + + void DeleteThis() + { + delete this; + } + + bool IsEqual(ISHDelegate *other) + { + return static_cast* >(other)->GetDeleg() == GetDeleg(); + } + + T &GetDeleg() + { + return m_Deleg; + } + }; + + struct IHookList + { + struct IIter + { + virtual bool End() = 0; + virtual void Next() = 0; + virtual ISHDelegate *Handler() = 0; + virtual int ThisPtrOffs() = 0; + }; + virtual IIter *GetIter() = 0; + virtual void ReleaseIter(IIter *pIter) = 0; + }; + + struct IIface + { + virtual void *GetPtr() = 0; + virtual IHookList *GetPreHooks() = 0; + virtual IHookList *GetPostHooks() = 0; + }; + + struct IVfnPtr + { + virtual void *GetVfnPtr() = 0; + virtual void *GetOrigEntry() = 0; + + virtual IIface *FindIface(void *ptr) = 0; + }; + + struct IHookManagerInfo + { + virtual IVfnPtr *FindVfnPtr(void *vfnptr) = 0; + + virtual void SetInfo(int vtbloffs, int vtblidx, const char *proto) = 0; + virtual void SetHookfuncVfnptr(void *hookfunc_vfnptr) = 0; + + // Added 23.12.2005 (yup! I'm coding RIGHT BEFORE CHRISTMAS!) + // If the hookman doesn't set this, it defaults 0 + // SourceHook prefers hookmans with higher version numbers + virtual void SetVersion(int version) = 0; + }; + + class AutoHookIter + { + IHookList *m_pList; + IHookList::IIter *m_pIter; + public: + AutoHookIter(IHookList *pList) + : m_pList(pList), m_pIter(pList->GetIter()) + { + } + + ~AutoHookIter() + { + if (m_pList) + m_pList->ReleaseIter(m_pIter); + } + + bool End() + { + return m_pIter->End(); + } + + void Next() + { + m_pIter->Next(); + } + + ISHDelegate *Handler() + { + return m_pIter->Handler(); + } + + int ThisPtrOffs() + { + return m_pIter->ThisPtrOffs(); + } + + void SetToZero() + { + m_pList = 0; + } + }; + + template struct DeprecatedCallClass + { + virtual B *GetThisPtr() = 0; + virtual void *GetOrigFunc(int vtbloffs, int vtblidx) = 0; + }; + + // 09.08.2008 (6 AM, I just woke up, the others are still sleeping so i finally can use this notebook !!) + // - Today is an important day. + // I'm adding support for functions which return references. + + // How it works: + // SH_SETUPCALLS doesn't use plain rettype to store the temporary return values (plugin ret, orig ret, + // override ret) anymore; instead, it uses SourceHook::ReferenceCarrier::type + // this is typedefed to the original rettype normally, but if the rettype is a reference, it's a special class + // which stores the reference as a pointer, and implements constructors, operator= and a conversion operator. + // special cases were needed for getoverrideret / getorigret; these are implemented through the + // SourceHook::MacroRefHelpers structs. + // Furthermore, SetOverrideRet had to be changed a bit; see SourceHook::OverrideFunctor somewhere down in this file. + template struct ReferenceCarrier + { + typedef T type; + }; + + template struct ReferenceCarrier + { + class type + { + T *m_StoredRef; + public: + type() : m_StoredRef(NULL) + { + } + type(T& ref) : m_StoredRef(&ref) + { + } + + T& operator= (T& ref) + { + m_StoredRef = &ref; + return ref; + } + + operator T& () const + { + return *m_StoredRef; + } + }; + }; + + /** + * @brief The main SourceHook interface + */ + class ISourceHook + { + public: + /** + * @brief Return interface version + */ + virtual int GetIfaceVersion() = 0; + + /** + * @brief Return implementation version + */ + virtual int GetImplVersion() = 0; + + /** + * @brief Add a hook. + * + * @return True if the function succeeded, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param iface The interface pointer + * @param ifacesize The size of the class iface points to + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + virtual bool AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, + ISHDelegate *handler, bool post) = 0; + + /** + * @brief Removes a hook. + * + * @return True if the function succeeded, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param iface The interface pointer + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + virtual bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, + ISHDelegate *handler, bool post) = 0; + + /** + * @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins + * + * @param plug The unique identifier of the plugin in question + */ + virtual bool IsPluginInUse(Plugin plug) = 0; + + /** + * @brief Return a pointer to a callclass. Generate a new one if required. + * + * @param iface The interface pointer + * @param size Size of the class instance + */ + virtual DeprecatedCallClass *GetCallClass(void *iface, size_t size) = 0; + + /** + * @brief Release a callclass + * + * @param ptr Pointer to the callclass + */ + virtual void ReleaseCallClass(DeprecatedCallClass *ptr) = 0; + + virtual void SetRes(META_RES res) = 0; //!< Sets the meta result + virtual META_RES GetPrevRes() = 0; //!< Gets the meta result of the + //!< previously calledhandler + virtual META_RES GetStatus() = 0; //!< Gets the highest meta result + virtual const void *GetOrigRet() = 0; //!< Gets the original result. + //!< If not in post function, undefined + virtual const void *GetOverrideRet() = 0; //!< Gets the override result. + //!< If none is specified, NULL + virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer + ////////////////////////////////////////////////////////////////////////// + // For hook managers + virtual void HookLoopBegin(IIface *pIface) = 0; //!< Should be called when a hook loop begins + virtual void HookLoopEnd() = 0; //!< Should be called when a hook loop exits + virtual void SetCurResPtr(META_RES *mres) = 0; //!< Sets pointer to the current meta result + virtual void SetPrevResPtr(META_RES *mres) = 0; //!< Sets pointer to previous meta result + virtual void SetStatusPtr(META_RES *mres) = 0; //!< Sets pointer to the status variable + virtual void SetIfacePtrPtr(void **pp) = 0; //!< Sets pointer to the interface this pointer + virtual void SetOrigRetPtr(const void *ptr) = 0; //!< Sets the original return pointer + virtual void SetOverrideRetPtr(void *ptr) = 0; //!< Sets the override result pointer + virtual bool ShouldContinue() = 0; //!< Returns false if the hook loop should exit + + /** + * @brief Remove a hook manager. Auto-removes all hooks attached to it from plugin plug. + * + * @param plug The owner of the hook manager + * @param pubFunc The hook manager's info function + */ + virtual void RemoveHookManager(Plugin plug, HookManagerPubFunc pubFunc) = 0; + + virtual void DoRecall() = 0; //!< Initiates a recall sequence + /* + HOW RECALLS WORK: + + The problem: + Users want the ability to change parameters of the called function + from inside their handler. + The solution: + 1) Mark as "recall" + 2) Recall the function + 3) => SH's hook func gets called: + 4) The first iterator points at the first hook the last hookfunc didn't execute yet + 5) does all iteration and returns normally + 6) The user's handler returns immediately + 7) The hook func returns immediately as well + + Also note that the recalled hookfunc starts with the status the recalling hookfunc + ended with. The last handler (doing the recall) is also able to specify its own + META_RES. + */ + + virtual void *GetOverrideRetPtr() = 0; //!< Returns the pointer set by SetOverrideRetPtr + + /** + * @brief Set up the hook loop. Equivalent to calling: + * SetStatusPtr, SetPrevResPtr, SetCurResPtr, SetIfacePtrPtr, SetOrigRetPtr, Get/SetOverrideRetPtr + * + * @param statusPtr pointer to status variable + * @param prevResPtr pointer to previous result variable + * @param curResPtr pointer to current result variable + * @param ifacePtrPtr pointer to interface this pointer variable + * @param origRetPr pointer to original return value variable. NULL for void funcs + * @param overrideRetPtr pointer to override return value variable. NULL for void funcs + * + * @return Override Return Pointer the hookfunc should use (may differ from overrideRetPtr + * when the hook func is being called as part of a recall + */ + virtual void *SetupHookLoop(META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr, + void **ifacePtrPtr, const void *origRetPtr, void *overrideRetPtr) = 0; + + /** + * @brief Modes for the new AddHook + */ + enum AddHookMode + { + Hook_Normal, + Hook_VP, + Hook_DVP + }; + + /** + * @brief Add a (VP) hook. + * + * @return non-zero hook id on success, 0 otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param mode Can be either Hook_Normal or Hook_VP (vtable-wide hook) + * @param iface The interface pointer + * @param ifacesize The size of the class iface points to + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + virtual int AddHookNew(Plugin plug, AddHookMode mode, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, + ISHDelegate *handler, bool post) = 0; + + /** + * @brief Remove a VP hook by ID. + * + * @return true on success, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param hookid The hook id (returned by AddHookNew) + */ + virtual bool RemoveHookByID(Plugin plug, int hookid) = 0; + + /** + * @brief Makes sure that hooks are going to be ignored on the next call of vfnptr + * + * @param plug The unique identifier of the plugin that calls this function + * @param vfnptr The virtual function pointer of the function in question + */ + virtual void SetIgnoreHooks(Plugin plug, void *vfnptr) = 0; + + /** + * @brief Reverses SetIgnoreHooks' effect + * + * @param plug The unique identifier of the plugin that calls this function + * @param vfnptr The virtual function pointer of the function in question + */ + virtual void ResetIgnoreHooks(Plugin plug, void *vfnptr) = 0; + + /** + * @brief Finds the original entry of a virtual function pointer + * + * @param vfnptr The virtual function pointer + * @return The original entry if the virtual function pointer has been patched; NULL otherwise. + */ + virtual void *GetOrigVfnPtrEntry(void *vfnptr) = 0; + }; + + // For META_RESULT_ORIG_RET and META_RESULT_OVERRIDE_RET: + // These have to be able to return references. If T is a reference, the pointers returned + // from the SH_GLOB_SHPTR are pointers to instances of ReferenceCarrier::type. + template struct MacroRefHelpers + { + inline static const T* GetOrigRet(ISourceHook *shptr) + { + return reinterpret_cast(shptr->GetOrigRet()); + } + inline static const T* GetOverrideRet(ISourceHook *shptr) + { + return reinterpret_cast(shptr->GetOverrideRet()); + } + }; + + template struct MacroRefHelpers + { + inline static T* GetOrigRet(ISourceHook *shptr) + { + T &ref = *reinterpret_cast::type *>(shptr->GetOrigRet()); + return &ref; + } + inline static T* GetOverrideRet(ISourceHook *shptr) + { + T &ref = *reinterpret_cast::type *>(shptr->GetOverrideRet()); + return &ref; + } + }; + + // For source-level compatibility + template struct CallClass + { + T *ptr; + + CallClass(T *p) : ptr(p) + { + } + + operator T*() + { + return ptr; + } + }; + + typedef CallClass GenericCallClass; + typedef CallClass ManualCallClass; + + template + CallClass *GetCallClass(T *p) + { + return new CallClass(p); + } + + template + void ReleaseCallClass(CallClass *p) + { + delete p; + } + + template + void *GetOrigVfnPtrEntry(X *pInstance, MFP mfp, ISourceHook *pSH) + { + SourceHook::MemFuncInfo info = {true, -1, 0, 0}; + SourceHook::GetFuncInfo(pInstance, mfp, info); + + void *vfnptr = reinterpret_cast( + *reinterpret_cast(reinterpret_cast(pInstance) + info.thisptroffs + info.vtbloffs) + info.vtblindex); + + void *origentry = pSH->GetOrigVfnPtrEntry(vfnptr); + + return origentry ? origentry : *reinterpret_cast(vfnptr); + } +} + +/************************************************************************/ +/* High level interface */ +/************************************************************************/ +#define META_RESULT_STATUS SH_GLOB_SHPTR->GetStatus() +#define META_RESULT_PREVIOUS SH_GLOB_SHPTR->GetPrevRes() +#define META_RESULT_ORIG_RET(type) *SourceHook::MacroRefHelpers::GetOrigRet(SH_GLOB_SHPTR) +#define META_RESULT_OVERRIDE_RET(type) *SourceHook::MacroRefHelpers::GetOverrideRet(SH_GLOB_SHPTR) +#define META_IFACEPTR(type) reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()) + +#define SET_META_RESULT(result) SH_GLOB_SHPTR->SetRes(result) +#define RETURN_META(result) do { SET_META_RESULT(result); return; } while(0) +#define RETURN_META_VALUE(result, value) do { SET_META_RESULT(result); return (value); } while(0) + +// If a hook on a function which returns a reference does not want to specify a return value, +// it can use this macro. +// ONLY USE THIS WITH MRES_IGNORED AND MRES_HANDLED !!! +#define RETURN_META_NOREF(result, rettype) do { SET_META_RESULT(result); return reinterpret_cast(*SH_GLOB_SHPTR); } while(0) + +// only call these from the hook handlers directly! +// :TODO: enforce it ? + +// Why take a memfuncptr instead of iface and func when we have to deduce the iface anyway now? +// Well, without it, there'd be no way to specify which overloaded version we want in _VALUE + +// SourceHook::SetOverrideRet is defined later. +#define RETURN_META_NEWPARAMS(result, memfuncptr, newparams) \ + do { \ + SET_META_RESULT(result); \ + SH_GLOB_SHPTR->DoRecall(); \ + (SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams; \ + RETURN_META(MRES_SUPERCEDE); \ + } while (0) + +#define RETURN_META_VALUE_NEWPARAMS(result, value, memfuncptr, newparams) \ + do { \ + SET_META_RESULT(result); \ + SH_GLOB_SHPTR->DoRecall(); \ + if ((result) >= MRES_OVERRIDE) \ + { \ + /* meh, set the override result here because we don't get a chance to return */ \ + /* before continuing the hook loop through the recall */ \ + SourceHook::SetOverrideResult(memfuncptr)(SH_GLOB_SHPTR, value); \ + } \ + RETURN_META_VALUE(MRES_SUPERCEDE, \ + (SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams); \ + } while (0) + +// :TODO: thisptroffs in MNEWPARAMS ?? + +#if SH_COMP == SH_COMP_MSVC + +#define SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname) \ + union \ + { \ + SH_MFHCls(hookname)::ECMFP mfp; \ + void *addr; \ + } u; \ + SourceHook::EmptyClass *thisptr = reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()); \ + u.addr = (*reinterpret_cast(reinterpret_cast(thisptr) + SH_MFHCls(hookname)::ms_MFI.vtbloffs))[ \ + SH_MFHCls(hookname)::ms_MFI.vtblindex]; + +#elif SH_COMP == SH_COMP_GCC + +#define SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname) \ + union \ + { \ + SH_MFHCls(hookname)::ECMFP mfp; \ + struct \ + { \ + void *addr; \ + intptr_t adjustor; \ + } s; \ + } u; \ + SourceHook::EmptyClass *thisptr = reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()); \ + u.s.addr = (*reinterpret_cast(reinterpret_cast(thisptr) + SH_MFHCls(hookname)::ms_MFI.vtbloffs))[ \ + SH_MFHCls(hookname)::ms_MFI.vtblindex]; \ + u.s.adjustor = 0; + +#endif + +#define RETURN_META_MNEWPARAMS(result, hookname, newparams) \ + do { \ + SET_META_RESULT(result); \ + SH_GLOB_SHPTR->DoRecall(); \ + SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname); \ + (thisptr->*(u.mfp)) newparams; \ + RETURN_META(MRES_SUPERCEDE); \ + } while (0) + +#define RETURN_META_VALUE_MNEWPARAMS(result, value, hookname, newparams) \ + do { \ + SET_META_RESULT(result); \ + SH_GLOB_SHPTR->DoRecall(); \ + if ((result) >= MRES_OVERRIDE) \ + { \ + /* see RETURN_META_VALUE_NEWPARAMS */ \ + SourceHook::SetOverrideResult(SH_GLOB_SHPTR, value); \ + } \ + SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname); \ + RETURN_META_VALUE(MRES_SUPERCEDE, (thisptr->*(u.mfp)) newparams); \ + } while (0) + +#define SH_MANUALHOOK_RECONFIGURE(hookname, pvtblindex, pvtbloffs, pthisptroffs) \ + do { \ + SH_GLOB_SHPTR->RemoveHookManager(SH_GLOB_PLUGPTR, SH_MFHCls(hookname)::HookManPubFunc); \ + SH_MFHCls(hookname)::ms_MFI.thisptroffs = pthisptroffs; \ + SH_MFHCls(hookname)::ms_MFI.vtblindex = pvtblindex; \ + SH_MFHCls(hookname)::ms_MFI.vtbloffs = pvtbloffs; \ + } while (0) + + +#define SH_GET_ORIG_VFNPTR_ENTRY(inst, mfp) (SourceHook::GetOrigVfnPtrEntry(inst, mfp, SH_GLOB_SHPTR)) + +// For source-level compatibility + +#define SH_GET_CALLCLASS(ptr) SourceHook::GetCallClass(ptr) +#define SH_GET_MCALLCLASS(ptr, size) SourceHook::GetCallClass(reinterpret_cast(ptr)) +#define SH_RELEASE_CALLCLASS(ptr) SourceHook::ReleaseCallClass(ptr) + +// New ADD / REMOVE macros. +#define SH_STATIC(func) fastdelegate::MakeDelegate(func) +#define SH_MEMBER(inst, func) fastdelegate::MakeDelegate(inst, func) + +#define SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ + __SourceHook_FHAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ + post, handler) + +#define SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ + __SourceHook_FHRemove##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ + post, handler) + +#define SH_ADD_MANUALHOOK(hookname, ifaceptr, handler, post) \ + __SourceHook_FHMAdd##hookname(reinterpret_cast(ifaceptr), post, handler) + +#define SH_REMOVE_MANUALHOOK(hookname, ifaceptr, handler, post) \ + __SourceHook_FHMRemove##hookname(reinterpret_cast(ifaceptr), post, handler) + +#define SH_ADD_VPHOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ + __SourceHook_FHVPAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ + post, handler, false) + +#define SH_ADD_DVPHOOK(ifacetype, ifacefunc, vtableptr, handler, post) \ + __SourceHook_FHVPAdd##ifacetype##ifacefunc(reinterpret_cast(vtableptr), \ + post, handler, true) + +#define SH_ADD_MANUALVPHOOK(hookname, ifaceptr, handler, post) \ + __SourceHook_FHMVPAdd##hookname(reinterpret_cast(ifaceptr), post, handler, false) + +#define SH_ADD_MANUALDVPHOOK(hookname, vtableptr, handler, post) \ + __SourceHook_FHMVPAdd##hookname(reinterpret_cast(vtableptr), post, handler, true) + +#define SH_REMOVE_HOOK_ID(hookid) \ + (SH_GLOB_SHPTR->RemoveHookByID(SH_GLOB_PLUGPTR, hookid)) + +// Old macros +// !! These are now deprecated. Instead, use one of these: +// SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) +// SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(inst, func), post) + +#define SH_ADD_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \ + SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) +#define SH_ADD_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \ + SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) + +// SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) +// SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(inst, func), post) + +#define SH_REMOVE_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \ + SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) +#define SH_REMOVE_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \ + SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) + +// SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) +// SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(inst, func), post) + +#define SH_ADD_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \ + SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) +#define SH_ADD_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \ + SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) + +// SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) +// SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(inst, func), post) + +#define SH_REMOVE_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \ + SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) +#define SH_REMOVE_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \ + SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) + +#define SH_NOATTRIB + + + + +#if SH_COMP == SH_COMP_MSVC +# define SH_SETUP_MFP(mfp) \ + reinterpret_cast(&mfp)[0] = vfnptr_origentry; +#elif SH_COMP == SH_COMP_GCC +# define SH_SETUP_MFP(mfp) \ + reinterpret_cast(&mfp)[0] = vfnptr_origentry; \ + reinterpret_cast(&mfp)[1] = 0; +#else +# error Not supported yet. +#endif + +////////////////////////////////////////////////////////////////////////// +#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov +#define SH_MFHCls(hookname) __SourceHook_MFHCls_##hookname + +#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \ + SH_FHCls(ifacetype,ifacefunc,overload)() \ + { \ + GetFuncInfo(funcptr, ms_MFI); \ + } \ + \ + static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::IHookManagerInfo *param) \ + { \ + using namespace ::SourceHook; \ + GetFuncInfo(funcptr, ms_MFI); \ + /* Verify interface version */ \ + if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \ + return 1; \ + if (SH_GLOB_SHPTR->GetImplVersion() < SH_IMPL_VERSION) \ + return 1; \ + \ + if (action == HA_GetInfo) \ + { \ + param->SetVersion(SH_HOOKMAN_VERSION); \ + param->SetInfo(ms_MFI.vtbloffs, ms_MFI.vtblindex, \ + reinterpret_cast(&ms_Proto)); \ + \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \ + param->SetHookfuncVfnptr( \ + reinterpret_cast(reinterpret_cast(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]); \ + return 0; \ + } \ + else if (action == HA_Register) \ + { \ + ms_HI = param; \ + return 0; \ + } \ + else if (action == HA_Unregister) \ + { \ + ms_HI = NULL; \ + return 0; \ + } \ + else \ + return 1; \ + } + +// It has to be possible to use the macros in namespaces +// -> So we need to access and extend the global SourceHook namespace +// We use a namespace alias for this +#define SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, funcptr) \ + struct SH_FHCls(ifacetype,ifacefunc,overload) \ + { \ + static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \ + static ::SourceHook::MemFuncInfo ms_MFI; \ + static ::SourceHook::IHookManagerInfo *ms_HI; \ + static ::SourceHook::ProtoInfo ms_Proto; \ + SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) + +#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, funcptr) \ + }; \ + SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \ + ::SourceHook::MemFuncInfo SH_FHCls(ifacetype,ifacefunc,overload)::ms_MFI; \ + ::SourceHook::IHookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \ + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \ + SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ + { \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0 || !mfi.isVirtual) \ + return false; /* No non-virtual functions / virtual inheritance supported */ \ + \ + return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, ::SourceHook::ISourceHook::Hook_Normal, iface, mfi.thisptroffs, \ + SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, \ + new CSHDelegate(handler), post); \ + } \ + int __SourceHook_FHVPAdd##ifacetype##ifacefunc(void *iface, bool post, \ + SH_FHCls(ifacetype,ifacefunc,overload)::FD handler, bool direct) \ + { \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0 || !mfi.isVirtual) \ + return false; /* No non-virtual functions / virtual inheritance supported */ \ + \ + return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, \ + direct ? ::SourceHook::ISourceHook::Hook_DVP : ::SourceHook::ISourceHook::Hook_VP, \ + iface, mfi.thisptroffs, SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, \ + new CSHDelegate(handler), post); \ + } \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ + { \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0) \ + return false; /* No virtual inheritance supported */ \ + \ + CSHDelegate tmp(handler); \ + return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, mfi.thisptroffs, \ + SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, &tmp, post); \ + } \ + +#define SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, pvtbloffs, pvtblidx, pthisptroffs) \ + struct SH_MFHCls(hookname) \ + { \ + static SH_MFHCls(hookname) ms_Inst; \ + static ::SourceHook::MemFuncInfo ms_MFI; \ + static ::SourceHook::IHookManagerInfo *ms_HI; \ + static ::SourceHook::ProtoInfo ms_Proto; \ + \ + SH_MFHCls(hookname)() \ + { \ + ms_MFI.isVirtual = true; \ + ms_MFI.thisptroffs = pthisptroffs; \ + ms_MFI.vtblindex = pvtblidx; \ + ms_MFI.vtbloffs = pvtbloffs; \ + } \ + static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::IHookManagerInfo *param) \ + { \ + using namespace ::SourceHook; \ + /* we don't set ms_MFI here because manual hookmans can be reconfigured */ \ + /* :FIXME: possible problem: someone adding a hook from a constructor of a global entity */ \ + /* which is construced before SH_MFHCls(hookname)() gets called? */ \ + /* Verify interface version */ \ + if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \ + return 1; \ + if (SH_GLOB_SHPTR->GetImplVersion() < SH_IMPL_VERSION) \ + return 1; \ + \ + if (action == HA_GetInfo) \ + { \ + param->SetVersion(SH_HOOKMAN_VERSION); \ + param->SetInfo(ms_MFI.vtbloffs, ms_MFI.vtblindex, \ + reinterpret_cast(&ms_Proto)); \ + \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(&SH_MFHCls(hookname)::Func, mfi); \ + param->SetHookfuncVfnptr( \ + reinterpret_cast(reinterpret_cast(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]); \ + return 0; \ + } \ + else if (action == HA_Register) \ + { \ + ms_HI = param; \ + return 0; \ + } \ + else if (action == HA_Unregister) \ + { \ + ms_HI = NULL; \ + return 0; \ + } \ + else \ + return 1; \ + } + +#define SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, pvtbloffs, pvtblidx, pthisptroffs) \ + }; \ + SH_MFHCls(hookname) SH_MFHCls(hookname)::ms_Inst; \ + ::SourceHook::MemFuncInfo SH_MFHCls(hookname)::ms_MFI; \ + ::SourceHook::IHookManagerInfo *SH_MFHCls(hookname)::ms_HI; \ + int __SourceHook_FHMAdd##hookname(void *iface, bool post, \ + SH_MFHCls(hookname)::FD handler) \ + { \ + return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, ::SourceHook::ISourceHook::Hook_Normal, iface, pthisptroffs, \ + SH_MFHCls(hookname)::HookManPubFunc, \ + new ::SourceHook::CSHDelegate(handler), post); \ + } \ + int __SourceHook_FHMVPAdd##hookname(void *iface, bool post, \ + SH_MFHCls(hookname)::FD handler, bool direct) \ + { \ + return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, \ + direct ? ::SourceHook::ISourceHook::Hook_DVP : ::SourceHook::ISourceHook::Hook_VP, \ + iface, pthisptroffs, SH_MFHCls(hookname)::HookManPubFunc, \ + new ::SourceHook::CSHDelegate(handler), post); \ + } \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + SH_MFHCls(hookname)::FD handler) \ + { \ + ::SourceHook::CSHDelegate tmp(handler); \ + return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, pthisptroffs, \ + SH_MFHCls(hookname)::HookManPubFunc, &tmp, post); \ + } \ + + +#define SH_SETUPCALLS(rettype, paramtypes, params) \ + /* 1) Find the vfnptr */ \ + using namespace ::SourceHook; \ + void *ourvfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \ + IVfnPtr *vfnptr = ms_HI->FindVfnPtr(ourvfnptr); \ + SH_ASSERT(vfnptr, ("Called with vfnptr 0x%p which couldn't be found in the list", ourvfnptr)); \ + \ + void *vfnptr_origentry = vfnptr->GetOrigEntry(); \ + /* ... and the iface */ \ + IIface *ifinfo = vfnptr->FindIface(reinterpret_cast(this)); \ + if (!ifinfo) \ + { \ + /* The iface info was not found. Redirect the call to the original function. */ \ + rettype (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + return (reinterpret_cast(this)->*mfp)params; \ + } \ + /* 2) Declare some vars and set it up */ \ + SH_GLOB_SHPTR->HookLoopBegin(ifinfo); \ + IHookList *prelist = ifinfo->GetPreHooks(); \ + IHookList *postlist = ifinfo->GetPostHooks(); \ + META_RES status = MRES_IGNORED; \ + META_RES prev_res; \ + META_RES cur_res; \ + typedef ReferenceCarrier::type my_rettype; \ + my_rettype orig_ret; \ + my_rettype override_ret; \ + my_rettype plugin_ret; \ + void* ifptr; \ + my_rettype *pOverrideRet = reinterpret_cast(SH_GLOB_SHPTR->SetupHookLoop( \ + &status, &prev_res, &cur_res, &ifptr, &orig_ret, &override_ret)); + +#define SH_CALL_HOOKS(post, params) \ + if (SH_GLOB_SHPTR->ShouldContinue()) \ + { \ + prev_res = MRES_IGNORED; \ + for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \ + { \ + cur_res = MRES_IGNORED; \ + ifptr = reinterpret_cast(reinterpret_cast(this) - iter.ThisPtrOffs()); \ + plugin_ret = reinterpret_cast*>(iter.Handler())->GetDeleg() params; \ + prev_res = cur_res; \ + if (cur_res > status) \ + status = cur_res; \ + if (cur_res >= MRES_OVERRIDE) \ + *pOverrideRet = plugin_ret; \ + if (!SH_GLOB_SHPTR->ShouldContinue()) \ + { \ + iter.SetToZero(); \ + break; \ + } \ + } \ + } + +#define SH_CALL_ORIG(rettype, paramtypes, params) \ + if (status != MRES_SUPERCEDE) \ + { \ + rettype (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + orig_ret = (reinterpret_cast(this)->*mfp)params; \ + } \ + else \ + orig_ret = override_ret; \ + +#define SH_RETURN() \ + SH_GLOB_SHPTR->HookLoopEnd(); \ + return status >= MRES_OVERRIDE ? *pOverrideRet : orig_ret; + +#define SH_HANDLEFUNC(paramtypes, params, rettype) \ + SH_SETUPCALLS(rettype, paramtypes, params) \ + SH_CALL_HOOKS(pre, params) \ + SH_CALL_ORIG(rettype, paramtypes, params) \ + SH_CALL_HOOKS(post, params) \ + SH_RETURN() + +////////////////////////////////////////////////////////////////////////// +#define SH_SETUPCALLS_void(paramtypes, params) \ + /* 1) Find the vfnptr */ \ + using namespace ::SourceHook; \ + void *ourvfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \ + IVfnPtr *vfnptr = ms_HI->FindVfnPtr(ourvfnptr); \ + SH_ASSERT(vfnptr, ("Called with vfnptr 0x%p which couldn't be found in the list", ourvfnptr)); \ + \ + void *vfnptr_origentry = vfnptr->GetOrigEntry(); \ + /* ... and the iface */ \ + IIface *ifinfo = vfnptr->FindIface(reinterpret_cast(this)); \ + if (!ifinfo) \ + { \ + /* The iface info was not found. Redirect the call to the original function. */ \ + void (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + (reinterpret_cast(this)->*mfp)params; \ + return; \ + } \ + /* 2) Declare some vars and set it up */ \ + SH_GLOB_SHPTR->HookLoopBegin(ifinfo); \ + IHookList *prelist = ifinfo->GetPreHooks(); \ + IHookList *postlist = ifinfo->GetPostHooks(); \ + META_RES status = MRES_IGNORED; \ + META_RES prev_res; \ + META_RES cur_res; \ + void* ifptr; \ + SH_GLOB_SHPTR->SetupHookLoop(&status, &prev_res, &cur_res, &ifptr, NULL, NULL); \ + +#define SH_CALL_HOOKS_void(post, params) \ + if (SH_GLOB_SHPTR->ShouldContinue()) \ + { \ + prev_res = MRES_IGNORED; \ + for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \ + { \ + cur_res = MRES_IGNORED; \ + ifptr = reinterpret_cast(reinterpret_cast(this) - iter.ThisPtrOffs()); \ + reinterpret_cast*>(iter.Handler())->GetDeleg() params; \ + prev_res = cur_res; \ + if (cur_res > status) \ + status = cur_res; \ + if (!SH_GLOB_SHPTR->ShouldContinue()) \ + { \ + iter.SetToZero(); \ + break; \ + } \ + } \ + } + +#define SH_CALL_ORIG_void(paramtypes, params) \ + if (status != MRES_SUPERCEDE) \ + { \ + void (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + (reinterpret_cast(this)->*mfp)params; \ + } + +#define SH_RETURN_void() \ + SH_GLOB_SHPTR->HookLoopEnd(); + +#define SH_HANDLEFUNC_void(paramtypes, params) \ + SH_SETUPCALLS_void(paramtypes, params) \ + SH_CALL_HOOKS_void(pre, params) \ + SH_CALL_ORIG_void(paramtypes, params) \ + SH_CALL_HOOKS_void(post, params) \ + SH_RETURN_void() + + +// Special vafmt handlers +// :TODO: what +#define SH_HANDLEFUNC_vafmt(paramtypes, params_orig, params_plug, rettype) \ + SH_SETUPCALLS(rettype, paramtypes, params_orig) \ + SH_CALL_HOOKS(pre, params_plug) \ + SH_CALL_ORIG(rettype, paramtypes, params_orig) \ + SH_CALL_HOOKS(post, params_plug) \ + SH_RETURN() + +#define SH_HANDLEFUNC_void_vafmt(paramtypes, params_orig, params_plug) \ + SH_SETUPCALLS_void(paramtypes, params_orig) \ + SH_CALL_HOOKS_void(pre, params_plug) \ + SH_CALL_ORIG_void(paramtypes, params_orig) \ + SH_CALL_HOOKS_void(post, params_plug) \ + SH_RETURN_void() + +////////////////////////////////////////////////////////////////////////// + +// :FIXME: +// sizeof on references returns the size of the datatype, NOT the pointer size or something +// -> one should probably flag references in __SourceHook_ParamSizes_* ! +// or simply assume that their size is sizeof(void*)=SH_PTRSIZE... could be doable through a simple template + +@[$1,0,$a: +// ********* Support for $1 arguments ********* +#define SH_DECL_HOOK$1(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1:, param$2@]) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]@[$1!=0:, @]rettype> FD; \ + virtual rettype Func(@[$2,1,$1|, :param$2 p$2@]) \ + { SH_HANDLEFUNC((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@]), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0@[$2,1,$1:, sizeof(param$2)@] }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + $1, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK$1_void(ifacetype, ifacefunc, attr, overload@[$2,1,$1:, param$2@]) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]> FD; \ + virtual void Func(@[$2,1,$1|, :param$2 p$2@]) \ + { SH_HANDLEFUNC_void((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@])); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0@[$2,1,$1:, sizeof(param$2)@] }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + $1, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK$1_vafmt(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1:, param$2@]) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate@($1+1)<@[$2,1,$1|, :param$2@]@[$1!=0:, @]const char *, rettype> FD; \ + virtual rettype Func(@[$2,1,$1|, :param$2 p$2@]@[$1!=0:, @]const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((@[$2,1,$1|, :param$2@]@[$1!=0:, @]...), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]"%s", buf), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1@[$2,1,$1:, sizeof(param$2)@] }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + $1, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK$1_void_vafmt(ifacetype, ifacefunc, attr, overload@[$2,1,$1:, param$2@]) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate@($1+1)<@[$2,1,$1|, :param$2@]@[$1!=0:, @]const char *> FD; \ + virtual void Func(@[$2,1,$1|, :param$2 p$2@]@[$1!=0:, @]const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((@[$2,1,$1|, :param$2@]@[$1!=0:, @]...), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]"%s", buf), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1@[$2,1,$1:, sizeof(param$2)@] }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + $1, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK$1(hookname, vtblidx, vtbloffs, thisptroffs, rettype@[$2,1,$1:, param$2@]) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]@[$1!=0:, @]rettype> FD; \ + virtual rettype Func(@[$2,1,$1|, :param$2 p$2@]) \ + { SH_HANDLEFUNC((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@]), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(@[$2,1,$1|, :param$2@]); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0@[$2,1,$1:, sizeof(param$2)@] }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + $1, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK$1_void(hookname, vtblidx, vtbloffs, thisptroffs@[$2,1,$1:, param$2@]) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]> FD; \ + virtual void Func(@[$2,1,$1|, :param$2 p$2@]) \ + { SH_HANDLEFUNC_void((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@])); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(@[$2,1,$1|, :param$2@]); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0@[$2,1,$1:, sizeof(param$2)@] }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + $1, __SourceHook_ParamSizesM_##hookname); \ + +@] + + +////////////////////////////////////////////////////////////////////////// +// SH_CALL + +#define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \ +{ \ + using namespace ::SourceHook; \ + \ + m_pSH->SetIgnoreHooks(m_Plug, m_VfnPtr); \ + RetType tmpret = (m_ThisPtr->*m_MFP)call; \ + m_pSH->ResetIgnoreHooks(m_Plug, m_VfnPtr); \ + return tmpret; \ +} + +#define SH_MAKE_EXECUTABLECLASS_OB_void(call, prms) \ +{ \ + using namespace ::SourceHook; \ + \ + m_pSH->SetIgnoreHooks(m_Plug, m_VfnPtr); \ + (m_ThisPtr->*m_MFP)call; \ + m_pSH->ResetIgnoreHooks(m_Plug, m_VfnPtr); \ +} + +namespace SourceHook +{ + // Call Class Wrapper! + template struct CCW + { + typedef T type; + + // Get Real Pointer! + static inline T *GRP(T *p) + { + return p; + } + }; + + template struct CCW< CallClass > + { + typedef T type; + + // Get Real Pointer! + static inline T *GRP(CallClass *p) + { + return p->ptr; + } + }; + +@[$1,0,$a: + // Support for $1 arguments + template class ExecutableClass$1 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass$1(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(@[$2,1,$1|, :Param$2 p$2@]) const + SH_MAKE_EXECUTABLECLASS_OB((@[$2,1,$1|, :p$2@]), (@[$2,1,$1|, :Param$2@])) + + @[$2,$1+1,$a: + template <@[$3,$1+1,$2|, :class Param$3@]> RetType operator()(@[$3,1,$2|, :Param$3 p$3@]) const + SH_MAKE_EXECUTABLECLASS_OB((@[$3,1,$2|, :p$3@]), (@[$3,1,$2|, :Param$3@])) + @] + }; + + template class ExecutableClass$1 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass$1(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(@[$2,1,$1|, :Param$2 p$2@]) const + SH_MAKE_EXECUTABLECLASS_OB_void((@[$2,1,$1|, :p$2@]), (@[$2,1,$1|, :Param$2@])) + + @[$2,$1+1,$a: + template <@[$3,$1+1,$2|, :class Param$3@]> void operator()(@[$3,1,$2|, :Param$3 p$3@]) const + SH_MAKE_EXECUTABLECLASS_OB_void((@[$3,1,$2|, :p$3@]), (@[$3,1,$2|, :Param$3@])) + @] + }; +@] + +} + +#define SH__CALL_GET_VFNPTR_NORMAL \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(CCW::GRP(ptr), mfp, mfi); \ + void *vfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(CCW::GRP(ptr)) + mfi.thisptroffs + mfi.vtbloffs) + mfi.vtblindex); + +#define SH__CALL_GET_VFNPTR_MANUAL \ + using namespace ::SourceHook; \ + void *vfnptr = reinterpret_cast( \ + *reinterpret_cast( (reinterpret_cast(CCW::GRP(ptr)) + thisptroffs + vtbloffs) ) + vtblidx); \ + /* patch mfp */ \ + *reinterpret_cast(&mfp) = *reinterpret_cast(vfnptr); + +// SH_CALL needs to deduce the return type -> it uses templates and function overloading +// That's why SH_CALL takes two parameters: "mfp2" of type RetType(X::*mfp)(params), and "mfp" of type MFP +// The only purpose of the mfp2 parameter is to extract the return type + +@[$1,0,$a: +// Support for $1 arguments +template +SourceHook::ExecutableClass$1::type, MFP, RetType@[$2,1,$1:, Param$2@]> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass$1::type, MFP, RetType@[$2,1,$1:, Param$2@]>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass$1::type, MFP, RetType@[$2,1,$1:, Param$2@]> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@])const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass$1::type, MFP, RetType@[$2,1,$1:, Param$2@]>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass$1 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass$1( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} +@] + +#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300 +// GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it + +@[$1,0,$a: +// Support for $1 arguments +template +SourceHook::ExecutableClass$1::type, MFP, RetType@[$2,1,$1:, Param$2@]> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass$1::type, MFP, RetType@[$2,1,$1:, Param$2@]>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass$1::type, MFP, RetType@[$2,1,$1:, Param$2@]> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass$1::type, MFP, RetType@[$2,1,$1:, Param$2@]>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +@] + +#endif + +#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp), SH_GLOB_SHPTR, SH_GLOB_PLUGPTR) +#define SH_MCALL2(ptr, mfp, vtblidx, vtbloffs, thisptroffs) SH_MCALL3((ptr), (mfp), (mfp), (vtblidx), (vtbloffs), (thisptroffs), SH_GLOB_SHPTR, SH_GLOB_PLUGPTR) +#define SH_MCALL(ptr, mhookname) SH_MCALL2((ptr), SH_MFHCls(mhookname)::ECMFP(), SH_MFHCls(mhookname)::ms_MFI.vtblindex, \ + SH_MFHCls(mhookname)::ms_MFI.vtbloffs, SH_MFHCls(mhookname)::ms_MFI.thisptroffs) + +#undef SH_MAKE_EXECUTABLECLASS_OB + +////////////////////////////////////////////////////////////////////////// +// SetOverrideRet and RecallGetIface for recalls +// These take a ISourceHook pointer instead of using SH_GLOB_SHPTR directly +// The reason is that the user may want to redefine SH_GLOB_SHPTR - then the macros +// (META_RETURN_VALUE_NEWPARAMS) should obey the new pointer. + +namespace SourceHook +{ + template + void SetOverrideResult(ISourceHook *shptr, const RetType res) + { + *reinterpret_cast(shptr->GetOverrideRetPtr()) = res; + } + + // SetOverrideResult used to be implemented like this: + // SetOverrideResult(shptr, memfuncptr, return); + // normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference + // (it thought it was ambigous - the ref and non-ref type) + // so now SetOverrideResult(memfuncptr) deduces the ret type, and returns a functor which does the work + // new syntax: SetOverrideResult(memfuncptr)(shptr, return) + // This also allows us to create a special version for references which respects ReferenceCarrier. + + template struct OverrideFunctor + { + void operator()(ISourceHook *shptr, T res) + { + *reinterpret_cast(shptr->GetOverrideRetPtr()) = res; + } + }; + template struct OverrideFunctor + { + void operator()(ISourceHook *shptr, T &res) + { + // overrideretptr points to ReferenceCarrier + *reinterpret_cast::type *>(shptr->GetOverrideRetPtr()) = res; + } + }; +@[$1,0,$a: + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(@[$2,1,$1|, :Param$2@])) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(@[$2,1,$1|, :Param$2@])) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } +@] +} + +#endif + // The pope is dead. -> :( diff --git a/utils/mmsource/core-legacy/sourcehook/sh_list.h b/utils/mmsource/core-legacy/sourcehook/sh_list.h new file mode 100644 index 00000000..700a7a66 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/sh_list.h @@ -0,0 +1,291 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2008 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): David "BAILOPAN" Anderson +* ============================ +*/ + +#ifndef _INCLUDE_SMM_LIST_H +#define _INCLUDE_SMM_LIST_H + +#include +#include + +namespace SourceHook +{ + + //This class is from CSDM for AMX Mod X + /* + A circular, doubly-linked list with one sentinel node + + Empty: + m_Head = sentinel + m_Head->next = m_Head; + m_Head->prev = m_Head; + One element: + m_Head = sentinel + m_Head->next = node1 + m_Head->prev = node1 + node1->next = m_Head + node1->prev = m_Head + Two elements: + m_Head = sentinel + m_Head->next = node1 + m_Head->prev = node2 + node1->next = node2 + node1->prev = m_Head + node2->next = m_Head + node2->prev = node1 + */ + template + class List + { + public: + class iterator; + friend class iterator; + class ListNode + { + public: + ListNode(const T & o) : obj(o) { }; + ListNode() { }; + T obj; + ListNode *next; + ListNode *prev; + }; + private: + // Initializes the sentinel node. + // BAIL used malloc instead of new in order to bypass the need for a constructor. + ListNode *_Initialize() + { + ListNode *n = (ListNode *)malloc(sizeof(ListNode)); + n->next = n; + n->prev = n; + return n; + } + public: + List() : m_Head(_Initialize()), m_Size(0) + { + } + List(const List &src) : m_Head(_Initialize()), m_Size(0) + { + iterator iter; + for (iter=src.begin(); iter!=src.end(); iter++) + push_back( (*iter) ); + } + ~List() + { + clear(); + + // Don't forget to free the sentinel + if (m_Head) + { + free(m_Head); + m_Head = NULL; + } + } + void push_back(const T &obj) + { + ListNode *node = new ListNode(obj); + + node->prev = m_Head->prev; + node->next = m_Head; + m_Head->prev->next = node; + m_Head->prev = node; + + m_Size++; + } + size_t size() const + { + return m_Size; + } + + void clear() + { + ListNode *node = m_Head->next; + ListNode *temp; + m_Head->next = m_Head; + m_Head->prev = m_Head; + + // Iterate through the nodes until we find g_Head (the sentinel) again + while (node != m_Head) + { + temp = node->next; + delete node; + node = temp; + } + m_Size = 0; + } + bool empty() const + { + return (m_Size == 0); + } + T & back() + { + return m_Head->prev->obj; + } + private: + ListNode *m_Head; + size_t m_Size; + public: + class iterator + { + friend class List; + public: + iterator() + { + m_This = NULL; + } + iterator(const List &src) + { + m_This = src.m_Head; + } + iterator(ListNode *n) : m_This(n) + { + } + iterator(const iterator &where) + { + m_This = where.m_This; + } + //pre decrement + iterator & operator--() + { + if (m_This) + m_This = m_This->prev; + return *this; + } + //post decrement + iterator operator--(int) + { + iterator old(*this); + if (m_This) + m_This = m_This->prev; + return old; + } + + //pre increment + iterator & operator++() + { + if (m_This) + m_This = m_This->next; + return *this; + } + //post increment + iterator operator++(int) + { + iterator old(*this); + if (m_This) + m_This = m_This->next; + return old; + } + + const T & operator * () const + { + return m_This->obj; + } + T & operator * () + { + return m_This->obj; + } + + T * operator -> () + { + return &(m_This->obj); + } + const T * operator -> () const + { + return &(m_This->obj); + } + + bool operator != (const iterator &where) const + { + return (m_This != where.m_This); + } + bool operator ==(const iterator &where) const + { + return (m_This == where.m_This); + } + private: + ListNode *m_This; + }; + public: + iterator begin() const + { + return iterator(m_Head->next); + } + iterator end() const + { + return iterator(m_Head); + } + iterator erase(iterator &where) + { + ListNode *pNode = where.m_This; + iterator iter(where); + iter++; + + + // Works for all cases: empty list, erasing first element, erasing tail, erasing in the middle... + pNode->prev->next = pNode->next; + pNode->next->prev = pNode->prev; + + delete pNode; + m_Size--; + + return iter; + } + + iterator insert(iterator where, const T &obj) + { + // Insert obj right before where + + ListNode *node = new ListNode(obj); + ListNode *pWhereNode = where.m_This; + + pWhereNode->prev->next = node; + node->prev = pWhereNode->prev; + pWhereNode->prev = node; + node->next = pWhereNode; + + m_Size++; + + return iterator(node); + } + + public: + void remove(const T & obj) + { + iterator b; + for (b=begin(); b!=end(); b++) + { + if ( (*b) == obj ) + { + erase( b ); + break; + } + } + } + template + iterator find(const U & equ) const + { + iterator iter; + for (iter=begin(); iter!=end(); iter++) + { + if ( (*iter) == equ ) + return iter; + } + return end(); + } + List & operator =(const List &src) + { + clear(); + iterator iter; + for (iter=src.begin(); iter!=src.end(); iter++) + push_back( (*iter) ); + return *this; + } + }; +}; //NAMESPACE + +#endif //_INCLUDE_CSDM_LIST_H diff --git a/utils/mmsource/core-legacy/sourcehook/sh_listcat.h b/utils/mmsource/core-legacy/sourcehook/sh_listcat.h new file mode 100644 index 00000000..8eb74ca2 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/sh_listcat.h @@ -0,0 +1,147 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2007 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +// Used for VP-Hooks + +#ifndef _INCLUDE_SMM_LISTCAT_H +#define _INCLUDE_SMM_LISTCAT_H + +#include "sh_list.h" + +namespace SourceHook +{ + + // Only a very special-case forward iterator! + template + class ListCatIterator + { + List *m_pListLeft; + List *m_pListRight; + typename List::iterator m_Iter; + + void CheckLeftEmptyOnBegin() + { + // If the left list is empty and right is valid, GoToBegin sets m_Iter to m_Left + // End() checks for equality to m_Right.end() so it returns false + // then Next() corrupts by incrementing! + + // To avoid this, we skip left if it's empty. + if (m_pListLeft && m_pListLeft->empty() && m_pListRight) + { + m_Iter = m_pListRight->begin(); + } + } + public: + // At least one list has to be non-null! + ListCatIterator(List *pListLeft, List *pListRight) : m_pListLeft(pListLeft), m_pListRight(pListRight), + m_Iter(pListLeft ? pListLeft->begin() : pListRight->begin()) + { + CheckLeftEmptyOnBegin(); + } + + void GoToBegin() + { + m_Iter = m_pListLeft ? m_pListLeft->begin() : m_pListRight->begin(); + CheckLeftEmptyOnBegin(); + } + + bool End() + { + return m_pListRight ? (m_Iter == m_pListRight->end()) + : (m_Iter == m_pListLeft->end()); + } + + //pre increment + ListCatIterator & operator++() + { + ++m_Iter; + if (m_pListLeft && m_Iter == m_pListLeft->end()) + { + if (m_pListRight) + m_Iter = m_pListRight->begin(); + } + return *this; + } + //post increment + ListCatIterator operator++(int) + { + ListCatIterator old(*this); + + ++m_Iter; + if (m_pListLeft && m_Iter == m_pListLeft->end()) + { + if (m_pListRight) + m_Iter = m_pListRight->begin(); + } + + return old; + } + + const T & operator * () const + { + return *m_Iter; + } + T & operator * () + { + return *m_Iter; + } + + T * operator -> () + { + return &(*m_Iter); + } + const T * operator -> () const + { + return &(*m_Iter); + } + + bool operator != (const typename List::iterator &where) const + { + return (m_Iter != where); + } + bool operator ==(const typename List::iterator &where) const + { + return (m_Iter == where); + } + + ListCatIterator & operator = (const typename List::iterator &where) + { + m_Iter = where; + + if (m_pListLeft && m_Iter == m_pListLeft->end()) + { + if (m_pListRight) + m_Iter = m_pListRight->begin(); + + // :HACK HACK: RemoveHookById is not aware of ListCatIterator (yet? :TODO: Change it!) + // So we have to do this here... (look for the "Move all iterators pointing at this" section) + --m_Iter; + } + + return *this; + } + + ListCatIterator & operator = (const ListCatIterator &other) + { + m_Iter = other.m_Iter; + m_pListLeft = other.m_pListLeft; + m_pListRight = other.m_pListRight; + return *this; + } + + void SetListLeft(List *pList) + { + m_pListLeft = pList; + } + }; +} + +#endif + diff --git a/utils/mmsource/core-legacy/sourcehook/sh_memfuncinfo.h b/utils/mmsource/core-legacy/sourcehook/sh_memfuncinfo.h new file mode 100644 index 00000000..a2f2d8cb --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/sh_memfuncinfo.h @@ -0,0 +1,912 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2008 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +/** + * @brief This file provides a way for getting information about a member function. + * @file sh_memfuncinfo.h + */ + +#ifndef __SHINT_MEMFUNC_INFO_H__ +#define __SHINT_MEMFUNC_INFO_H__ + +namespace SourceHook +{ + + // Don Clugston: + // implicit_cast< > + // I believe this was originally going to be in the C++ standard but + // was left out by accident. It's even milder than static_cast. + // I use it instead of static_cast<> to emphasize that I'm not doing + // anything nasty. + // Usage is identical to static_cast<> + template + inline OutputClass implicit_cast(InputClass input){ + return input; + } + + + struct MemFuncInfo + { + bool isVirtual; // Is the function virtual? + int thisptroffs; // The this pointer the function expects to be called with + // If -1, you need to call the GetFuncInfo_GetThisPtr function + int vtblindex; // The function's index in the vtable (0-based, 1=second entry, 2=third entry, ...) + int vtbloffs; // The vtable pointer + }; + + // Ideas by Don Clugston. + // Check out his excellent paper: http://www.codeproject.com/cpp/FastDelegate.asp + + template struct MFI_Impl + { + template static inline void GetFuncInfo(MFP *mfp, MemFuncInfo &out) + { + static char weird_memfunc_pointer_exclamation_mark_arrow_error[N-1000]; + } + }; + +# if SH_COMP == SH_COMP_GCC + + template<> struct MFI_Impl<2*SH_PTRSIZE> // All of these have size==8/16 + { + struct GCC_MemFunPtr + { + union + { + void *funcadr; // always even + intptr_t vtable_index_plus1; // = vindex+1, always odd + }; + intptr_t delta; + }; + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + GCC_MemFunPtr *mfp_detail = (GCC_MemFunPtr*)&mfp; + out.thisptroffs = mfp_detail->delta; + if (mfp_detail->vtable_index_plus1 & 1) + { + out.vtblindex = (mfp_detail->vtable_index_plus1 - 1) / SH_PTRSIZE; + out.vtbloffs = 0; + out.isVirtual = true; + } + else + out.isVirtual = false; + } + }; + +# elif SH_COMP == SH_COMP_MSVC + + namespace + { + int MFI_GetVtblOffset(void *mfp) + { + unsigned char *addr = (unsigned char*)mfp; + if (*addr == 0xE9) // Jmp + { + // May or may not be! + // Check where it'd jump + addr += 5 /*size of the instruction*/ + *(unsigned long*)(addr + 1); + } + + // Check whether it's a virtual function call + // They look like this: + // 004125A0 8B 01 mov eax,dword ptr [ecx] + // 004125A2 FF 60 04 jmp dword ptr [eax+4] + // ==OR== + // 00411B80 8B 01 mov eax,dword ptr [ecx] + // 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h] + + // However, for vararg functions, they look like this: + // 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4] + // 0048F0B4 8B 00 mov eax,dword ptr [eax] + // 0048F0B6 FF 60 08 jmp dword ptr [eax+8] + // ==OR== + // 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4] + // 0048F0B4 8B 00 mov eax,dword ptr [eax] + // 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h] + + // With varargs, the this pointer is passed as if it was the first argument + + bool ok = false; + if (addr[0] == 0x8B && addr[1] == 0x44 && addr[2] == 0x24 && addr[3] == 0x04 && + addr[4] == 0x8B && addr[5] == 0x00) + { + addr += 6; + ok = true; + } + else if (addr[0] == 0x8B && addr[1] == 0x01) + { + addr += 2; + ok = true; + } + if (!ok) + return -1; + + if (*addr++ == 0xFF) + { + if (*addr == 0x60) + { + return *++addr / 4; + } + else if (*addr == 0xA0) + { + return *((unsigned int*)++addr) / 4; + } + else if (*addr == 0x20) + return 0; + else + return -1; + } + return -1; + } + } + + template<> struct MFI_Impl<1*SH_PTRSIZE> // simple ones + { + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + out.thisptroffs = 0; + out.vtbloffs = 0; + } + }; + + template<> struct MFI_Impl<2*SH_PTRSIZE> // more complicated ones! + { + struct MSVC_MemFunPtr2 + { + void *funcadr; + int delta; + }; + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + out.thisptroffs = reinterpret_cast(&mfp)->delta; + out.vtbloffs = 0; + } + }; + + // By Don Clugston, adapted + template<> struct MFI_Impl<3*SH_PTRSIZE> // WOW IT"S GETTING BIGGER OMGOMOGMG + { + class __single_inheritance GenericClass; + class GenericClass {}; + + struct MicrosoftVirtualMFP { + void (GenericClass::*codeptr)(); // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtable_index; // or 0 if no virtual inheritance + }; + + struct GenericVirtualClass : virtual public GenericClass + { + typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); + GenericVirtualClass * GetThis() { return this; } + }; + + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + // This pointer + /* + union { + MFP func; + GenericClass* (T::*ProbeFunc)(); + MicrosoftVirtualMFP s; + } u; + u.func = mfp; + union { + GenericVirtualClass::ProbePtrType virtfunc; + MicrosoftVirtualMFP s; + } u2; + + // Check that the horrible_cast<>s will work + typedef int ERROR_CantUsehorrible_cast[sizeof(mfp)==sizeof(u.s) + && sizeof(mfp)==sizeof(u.ProbeFunc) + && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; + // Unfortunately, taking the address of a MF prevents it from being inlined, so + // this next line can't be completely optimised away by the compiler. + u2.virtfunc = &GenericVirtualClass::GetThis; + u.s.codeptr = u2.s.codeptr; + out.thisptroffs = (reinterpret_cast(NULL)->*u.ProbeFunc)(); + */ + out.thisptroffs = -1; + out.vtbloffs = 0; + } + }; + + // Don: Nasty hack for Microsoft and Intel (IA32 and Itanium) + // unknown_inheritance classes go here + // This is probably the ugliest bit of code I've ever written. Look at the casts! + // There is a compiler bug in MSVC6 which prevents it from using this code. + template<> struct MFI_Impl<4*SH_PTRSIZE> // THE BIGGEST ONE!!!1GABEN + { + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + + // The member function pointer is 16 bytes long. We can't use a normal cast, but + // we can use a union to do the conversion. + union { + MFP func; + // In VC++ and ICL, an unknown_inheritance member pointer + // is internally defined as: + struct { + void *m_funcaddress; // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtordisp; // #bytes to add to 'this' to find the vtable + int vtable_index; // or 0 if no virtual inheritance + } s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(u.func)==sizeof(u.s)? 1 : -1]; + u.func = mfp; + int virtual_delta = 0; + if (u.s.vtable_index) { // Virtual inheritance is used + /* + // First, get to the vtable. + // It is 'vtordisp' bytes from the start of the class. + int * vtable = *reinterpret_cast( + reinterpret_cast(thisptr) + u.s.vtordisp ); + + // 'vtable_index' tells us where in the table we should be looking. + virtual_delta = u.s.vtordisp + *reinterpret_cast( + reinterpret_cast(vtable) + u.s.vtable_index); + // The int at 'virtual_delta' gives us the amount to add to 'this'. + // Finally we can add the three components together. Phew! + out.thisptr = reinterpret_cast( + reinterpret_cast(thisptr) + u.s.delta + virtual_delta); + */ + out.vtbloffs = u.s.vtordisp; + out.thisptroffs = -1; + } + else + { + out.vtbloffs = out.vtblindex < 0 ? 0 : u.s.delta; + out.thisptroffs = u.s.delta; + } + }; + }; +# else +# error Unsupported compiler +# endif + + // This version does not take a this pointer + // Useful for hookdecls, as they ensure that mfp is correct through a static_cast + template inline void GetFuncInfo(X mfp, MemFuncInfo &out) + { + MFI_Impl::GetFuncInfo(mfp, out); + } + + // Versions which do take a this + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(), MemFuncInfo &out) + { + RetType(Y::*mfp2)() = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)() const, MemFuncInfo &out) + { + RetType(Y::*mfp2)() const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + // GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it +#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300 + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + +#endif + +} + +#endif diff --git a/utils/mmsource/core-legacy/sourcehook/sh_memory.h b/utils/mmsource/core-legacy/sourcehook/sh_memory.h new file mode 100644 index 00000000..8ec75360 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/sh_memory.h @@ -0,0 +1,340 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2008 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko, Scott "Damaged Soul" Ehlert +* Contributors: lancevorgin, XAD, theqizmo +* ============================ +*/ + +#ifndef __SHINT_MEMORY_H__ +#define __SHINT_MEMORY_H__ + +// Feb 17 / 2005: +// Unprotect now sets to readwrite +// The vtable doesn't need to be executable anyway + +# if SH_XP == SH_XP_WINAPI +# include +# define SH_MEM_READ 1 +# define SH_MEM_WRITE 2 +# define SH_MEM_EXEC 4 +# elif SH_XP == SH_XP_POSIX +# include +# include +# include +# include +# include +// http://www.die.net/doc/linux/man/man2/mprotect.2.html +# include +# ifndef PAGESIZE +# define PAGESIZE 4096 +# endif +# define SH_MEM_READ PROT_READ +# define SH_MEM_WRITE PROT_WRITE +# define SH_MEM_EXEC PROT_EXEC + +// We need to align addr down to pagesize on linux +// We assume PAGESIZE is a power of two +# define SH_LALIGN(x) (void*)((uintptr_t)(x) & ~(PAGESIZE-1)) +# define SH_LALDIF(x) ((uintptr_t)(x) & (PAGESIZE-1)) +# else +# error Unsupported OS/Compiler +# endif + + +namespace SourceHook +{ + static inline bool GetPageBits(void *addr, int *bits) + { +#if SH_SYS == SH_SYS_LINUX + // On linux, first check /proc/self/maps + unsigned long laddr = reinterpret_cast(addr); + + FILE *pF = fopen("/proc/self/maps", "r"); + if (pF) { + // Linux /proc/self/maps -> parse + // Format: + // lower upper prot stuff path + // 08048000-0804c000 r-xp 00000000 03:03 1010107 /bin/cat + unsigned long rlower, rupper; + char r, w, x; + while (fscanf(pF, "%lx-%lx %c%c%c", &rlower, &rupper, &r, &w, &x) != EOF) { + // Check whether we're IN THERE! + if (laddr >= rlower && laddr < rupper) { + fclose(pF); + *bits = 0; + if (r == 'r') + *bits |= SH_MEM_READ; + if (w == 'w') + *bits |= SH_MEM_WRITE; + if (x == 'x') + *bits |= SH_MEM_EXEC; + return true; + } + // Read to end of line + int c; + while ((c = fgetc(pF)) != '\n') { + if (c == EOF) + break; + } + if (c == EOF) + break; + } + fclose(pF); + return false; + } + pF = fopen("/proc/curproc/map", "r"); + if (pF) { + // FreeBSD /proc/curproc/map -> parse + // 0x804800 0x805500 13 15 0xc6e18960 r-x 21 0x0 COW NC vnode + unsigned long rlower, rupper, ignoreLong; + int ignoreInt; + char r, w, x; + while (fscanf(pF, "0x%lx 0x%lx %d %d 0x%lx %c%c%c", &rlower, &rupper, &ignoreInt, + &ignoreInt, &ignoreLong, &r, &w, &x) != EOF) { + // Check whether we're IN THERE! + if (laddr >= rlower && laddr < rupper) { + fclose(pF); + *bits = 0; + if (r == 'r') + *bits |= SH_MEM_READ; + if (r == 'w') + *bits |= SH_MEM_WRITE; + if (r == 'x') + *bits |= SH_MEM_EXEC; + return true; + } + // Read to end of line + int c; + while ((c = fgetc(pF)) != '\n') { + if (c == EOF) + break; + } + if (c == EOF) + break; + } + fclose(pF); + return false; + } + return false; +#elif SH_SYS == SH_SYS_APPLE +#elif SH_XP == SH_XP_WINAPI + SYSTEM_INFO info; + GetSystemInfo(&info); + + MEMORY_BASIC_INFORMATION mem; + size_t base = size_t(addr) & ~size_t(info.dwPageSize - 1); + if (!VirtualQuery((void *)base, &mem, sizeof(mem))) + return false; + switch (mem.Protect) { + case PAGE_EXECUTE: + *bits = SH_MEM_EXEC; + break; + case PAGE_EXECUTE_READ: + *bits = SH_MEM_EXEC | SH_MEM_READ; + break; + case PAGE_EXECUTE_READWRITE: + case PAGE_EXECUTE_WRITECOPY: + *bits = SH_MEM_EXEC | SH_MEM_READ | SH_MEM_WRITE; + break; + case PAGE_NOACCESS: + *bits = 0; + break; + case PAGE_READONLY: + *bits = SH_MEM_READ; + break; + case PAGE_READWRITE: + case PAGE_WRITECOPY: + *bits = SH_MEM_READ | SH_MEM_WRITE; + break; + default: + return false; + } + return true; +#endif + } + + inline bool SetMemAccess(void *addr, size_t len, int access) + { +# if SH_XP == SH_XP_POSIX + return mprotect(SH_LALIGN(addr), len + SH_LALDIF(addr), access)==0 ? true : false; +# else + DWORD tmp; + DWORD prot; + switch (access) + { + case SH_MEM_READ: + prot = PAGE_READONLY; break; + case SH_MEM_READ | SH_MEM_WRITE: + prot = PAGE_READWRITE; break; + case SH_MEM_READ | SH_MEM_EXEC: + prot = PAGE_EXECUTE_READ; break; + default: + case SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC: + prot = PAGE_EXECUTE_READWRITE; break; + } + return VirtualProtect(addr, len, prot, &tmp) ? true : false; +# endif + } + + inline bool MakePageWritable(void *addr) + { + int bits; + if (GetPageBits(addr, &bits)) { + if (bits & SH_MEM_WRITE) + return true; + bits |= SH_MEM_WRITE; + } else { + bits = SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC; + } + return SetMemAccess(addr, sizeof(void *), bits); + } + +#if SH_XP == SH_XP_POSIX + namespace + { + bool g_BadReadCalled; + jmp_buf g_BadReadJmpBuf; + +# if SH_SYS == SH_SYS_LINUX + static void BadReadHandler(int sig) + { + if (g_BadReadCalled) + longjmp(g_BadReadJmpBuf, 1); + } +# elif SH_SYS == SH_SYS_APPLE + static void BadReadHandler(int signal, siginfo_t* my_siginfo, void* my_context) + { + if (g_BadReadCalled) + longjmp(g_BadReadJmpBuf, 1); + } +# endif + } +#endif + + /** + * @brief Checks whether the specified memory region is (still) accessible + * + * @param addr The lower boundary + * @param len Length of the region to be checked + */ + namespace + { + bool ModuleInMemory(char *addr, size_t len) + { +#if SH_SYS == SH_SYS_LINUX + // On linux, first check /proc/self/maps + long lower = reinterpret_cast(addr); + long upper = lower + len; + + FILE *pF = fopen("/proc/self/maps", "r"); + if (pF) + { + // Linux /proc/self/maps -> parse + // Format: + // lower upper prot stuff path + // 08048000-0804c000 r-xp 00000000 03:03 1010107 /bin/cat + long rlower, rupper; + while (fscanf(pF, "%lx-%lx", &rlower, &rupper) != EOF) + { + // Check whether we're IN THERE! + if (lower >= rlower && upper <= rupper) + { + fclose(pF); + return true; + } + // Read to end of line + int c; + while ((c = fgetc(pF)) != '\n') + { + if (c == EOF) + break; + } + if (c == EOF) + break; + } + fclose(pF); + return false; + } + pF = fopen("/proc/curproc/map", "r"); + if (pF) + { + // FreeBSD /proc/curproc/map -> parse + // 0x804800 0x805500 13 15 0xc6e18960 r-x 21 0x0 COW NC vnode + long rlower, rupper; + while (fscanf(pF, "0x%lx 0x%lx", &rlower, &rupper) != EOF) + { + // Check whether we're IN THERE! + if (lower >= rlower && upper <= rupper) + { + fclose(pF); + return true; + } + // Read to end of line + int c; + while ((c = fgetc(pF)) != '\n') + { + if (c == EOF) + break; + } + if (c == EOF) + break; + } + fclose(pF); + return false; + } + + // Both of the above failed, try to actually read and trap sigsegv (implemented by Damaged Soul) + void(*prevHandler)(int sig); + g_BadReadCalled = true; + + if (setjmp(g_BadReadJmpBuf)) + return true; + + prevHandler = signal(SIGSEGV, BadReadHandler); + + volatile const char *p = reinterpret_cast(addr); + char dummy; + + for (size_t i = 0; i < len; i++) + dummy = p[i]; + + g_BadReadCalled = false; + + signal(SIGSEGV, prevHandler); + + return false; +#elif SH_SYS == SH_SYS_APPLE + struct sigaction sa, osa; + sa.sa_sigaction = BadReadHandler; + sa.sa_flags = SA_SIGINFO | SA_RESTART; + + g_BadReadCalled = true; + + if (setjmp(g_BadReadJmpBuf)) + return false; + + if (sigaction(SIGBUS, &sa, &osa) == -1) + return false; + + volatile const char *p = reinterpret_cast(addr); + char dummy; + + for (size_t i = 0; i < len; i++) + dummy = p[i]; + + g_BadReadCalled = false; + + return true; +#elif SH_XP == SH_XP_WINAPI + // On Win32, simply use IsBadReadPtr + return !IsBadReadPtr(addr, len); +#endif + } + } +} + +#endif diff --git a/utils/mmsource/core-legacy/sourcehook/sh_stack.h b/utils/mmsource/core-legacy/sourcehook/sh_stack.h new file mode 100644 index 00000000..8ab91683 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/sh_stack.h @@ -0,0 +1,237 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2008 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +#ifndef __SH_STACK_H__ +#define __SH_STACK_H__ + +#include + +#define SH_STACK_DEFAULT_SIZE 4 + +namespace SourceHook +{ + // Vector + template class CStack + { + T *m_Elements; + size_t m_AllocatedSize; + size_t m_UsedSize; + public: + friend class iterator; + class iterator + { + CStack *m_pParent; + size_t m_Index; + public: + iterator(CStack *pParent, size_t id) : m_pParent(pParent), m_Index(id) + { + } + + iterator(CStack *pParent) : m_pParent(pParent), m_Index(0) + { + } + + iterator() : m_pParent(NULL), m_Index(0) + { + } + + T &operator *() + { + return m_pParent->m_Elements[m_Index]; + } + const T &operator *() const + { + return m_pParent->m_Elements[m_Index]; + } + + T * operator->() + { + return m_pParent->m_Elements + m_Index; + } + + const T * operator->() const + { + return m_pParent->m_Elements + m_Index; + } + + iterator & operator++() // preincrement + { + ++m_Index; + return (*this); + } + + iterator operator++(int) // postincrement + { + iterator tmp = *this; + ++m_Index; + return tmp; + } + + iterator & operator--() // predecrement + { + --m_Index; + return (*this); + } + + iterator operator--(int) // postdecrememnt + { + iterator tmp = *this; + --m_Index; + return tmp; + } + + bool operator==(const iterator & right) const + { + return (m_pParent == right.m_pParent && m_Index == right.m_Index); + } + + bool operator!=(const iterator & right) const + { + return !(*this == right); + } + }; + CStack() : m_Elements(new T[SH_STACK_DEFAULT_SIZE]), + m_AllocatedSize(SH_STACK_DEFAULT_SIZE), + m_UsedSize(0) + { + } + CStack(size_t size) : m_Elements(new T[size]), + m_AllocatedSize(size), + m_UsedSize(0) + { + } + + CStack(const CStack &other) : m_Elements(NULL), + m_AllocatedSize(0), + m_UsedSize(0) + { + reserve(other.m_AllocatedSize); + m_UsedSize = other.m_UsedSize; + for (size_t i = 0; i < m_UsedSize; ++i) + m_Elements[i] = other.m_Elements[i]; + } + + ~CStack() + { + if (m_Elements) + delete [] m_Elements; + } + + void operator=(const CStack &other) + { + if (m_AllocatedSize < other.m_AllocatedSize) + { + if (m_Elements) + delete [] m_Elements; + m_Elements = new T[other.m_AllocatedSize]; + m_AllocatedSize = other.m_AllocatedSize; + } + m_UsedSize = other.m_UsedSize; + for (size_t i = 0; i < m_UsedSize; ++i) + m_Elements[i] = other.m_Elements[i]; + } + + bool push(const T &val) + { + if (m_UsedSize + 1 == m_AllocatedSize) + { + // zOHNOES! REALLOCATE! + m_AllocatedSize *= 2; + T *newElements = new T[m_AllocatedSize]; + if (!newElements) + { + m_AllocatedSize /= 2; + return false; + } + if (m_Elements) + { + for (size_t i = 0; i < m_UsedSize; ++i) + newElements[i] = m_Elements[i]; + delete [] m_Elements; + } + m_Elements = newElements; + } + m_Elements[m_UsedSize++] = val; + return true; + } + + void pop() + { + --m_UsedSize; + } + + void popall() + { + m_UsedSize = 0; + } + + T &front() + { + return m_Elements[m_UsedSize - 1]; + } + + const T &front() const + { + return m_Elements[m_UsedSize - 1]; + } + + T &second() + { + return m_Elements[m_UsedSize - 2]; + } + + const T &second() const + { + return m_Elements[m_UsedSize - 2]; + } + + iterator begin() + { + return iterator(this, 0); + } + iterator end() + { + return iterator(this, m_UsedSize); + } + + size_t size() + { + return m_UsedSize; + } + size_t capacity() + { + return m_AllocatedSize; + } + bool empty() + { + return m_UsedSize == 0 ? true : false; + } + bool reserve(size_t size) + { + if (size > m_AllocatedSize) + { + T *newElements = new T[size]; + if (!newElements) + return false; + if (m_Elements) + { + for (size_t i = 0; i < m_UsedSize; ++i) + newElements[i] = m_Elements[i]; + delete [] m_Elements; + } + m_Elements = newElements; + m_AllocatedSize = size; + } + return true; + } + }; +}; //namespace SourceHook + +#endif diff --git a/utils/mmsource/core-legacy/sourcehook/sh_string.h b/utils/mmsource/core-legacy/sourcehook/sh_string.h new file mode 100644 index 00000000..9bb4624c --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/sh_string.h @@ -0,0 +1,401 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2008 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): David "BAILOPAN" Anderson +* ============================ +*/ + +/* AMX Mod X + * + * by the AMX Mod X Development Team + */ + +#ifndef _INCLUDE_CSTRING_H +#define _INCLUDE_CSTRING_H + +#include +#include + +namespace SourceHook +{ +class String +{ +public: + String() + { + v = NULL; + a_size = 0; + //assign(""); + } + + ~String() + { + if (v) + delete [] v; + } + + String(const char *src) + { + v = NULL; + a_size = 0; + assign(src); + } + + String(const String &src) + { + v = NULL; + a_size = 0; + assign(src.c_str()); + } + + bool operator ==(const String &other) + { + return (compare(other.c_str()) == 0); + } + + bool operator ==(const char *other) + { + return (compare(other) == 0); + } + + const char *c_str() { return v?v:""; } + + const char *c_str() const { return v?v:""; } + + void append(const char *t) + { + Grow(size() + strlen(t) + 1); + strcat(v, t); + } + + void append(const char c) + { + size_t len = size(); + Grow(len + 2); + v[len] = c; + v[len + 1] = '\0'; + } + + void append(String &d) + { + append(d.c_str()); + } + + void assign(const String &src) + { + assign(src.c_str()); + } + + void assign(const char *d) + { + if (!d) + { + clear(); + } else { + Grow(strlen(d) + 1, false); + strcpy(v, d); + } + } + + void clear() + { + if (v) + v[0] = '\0'; + } + + int compare (const char *d) const + { + if (!v) + return strcmp("", d); + else + return strcmp(v, d); + } + + //Added this for amxx inclusion + bool empty() const + { + if (!v) + return true; + + if (v[0] == '\0') + return true; + + return false; + } + + size_t size() const + { + if (v) + return strlen(v); + else + return 0; + } + + int find(const char c, int index = 0) const + { + int len = static_cast(size()); + if (len < 1) + return npos; + if (index >= len || index < 0) + return npos; + int i = 0; + for (i=index; i(size()); + if (len < 1) + return npos; + if (index >= len || index < npos) + return npos; + int i; + if (index == npos) + i = len - 1; + else + i = index; + + for (; i>=0; i--) + { + if (v[i] == c) + { + return i; + } + } + + return npos; + } + + bool is_space(int c) const + { + if (c == '\f' || c == '\n' || + c == '\t' || c == '\r' || + c == '\v' || c == ' ') + { + return true; + } + + return false; + } + + void trim() + { + if (!v) + return; + + unsigned int i = 0; + unsigned int j = 0; + size_t len = strlen(v); + + if (len == 1) + { + if (is_space(v[i])) + { + clear(); + return; + } + } + + unsigned char c0 = v[0]; + + if (is_space(c0)) + { + for (i=0; i len-start) + num = len - start; + //do the erasing + bool copyflag = false; + for (i=0; i=start && i= len || !v) + return ns; + + if (num == npos) + { + num = len - index; + } else if (index+num >= len) { + num = len - index; + } + + unsigned int i = 0; + unsigned int nslen = num + 2; + + ns.Grow(nslen); + + for (i=index; i= 65 && v[i] <= 90) + v[i] &= ~(1<<5); + } + } + + String & operator = (const String &src) + { + assign(src); + return *this; + } + + String & operator = (const char *src) + { + assign(src); + return *this; + + } + + char operator [] (unsigned int index) const + { + if (index > size() || !v) + { + return -1; + } else { + return v[index]; + } + } + + int at(int a) const + { + if (a < 0 || a >= (int)size() || !v) + return -1; + + return v[a]; + } + + bool at(int at, char c) + { + if (at < 0 || at >= (int)size() || !v) + return false; + + v[at] = c; + + return true; + } + +private: + void Grow(unsigned int d, bool copy=true) + { + if (d <= a_size) + return; + char *n = new char[d + 1]; + if (copy && v) + strcpy(n, v); + if (v) + delete [] v; + else + strcpy(n, ""); + v = n; + a_size = d + 1; + } + + char *v; + unsigned int a_size; +public: + static const int npos = -1; +}; + +}; //NAMESPACE + +#endif //_INCLUDE_CSTRING_H diff --git a/utils/mmsource/core-legacy/sourcehook/sh_tinyhash.h b/utils/mmsource/core-legacy/sourcehook/sh_tinyhash.h new file mode 100644 index 00000000..70e2ee8e --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/sh_tinyhash.h @@ -0,0 +1,534 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2008 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): David "BAILOPAN" Anderson +* ============================ +*/ + +#ifndef _INCLUDE_SH_TINYHASH_H_ +#define _INCLUDE_SH_TINYHASH_H_ + +#include "sh_list.h" + +#define _T_INIT_HASH_SIZE 32 + +namespace SourceHook +{ + template + int HashFunction(const K & k); + + template + int HashAlt(const U &u); + + template + int CompareAlt(const U &k1, const K &k2); + + template + int Compare(const K & k1, const K & k2); + + /** + * This is a tiny, growable hash class. + * Meant for quick and dirty dictionaries only! + */ + template + class THash + { + public: + struct THashNode + { + THashNode(const K & k, const V & v) : + key(k), val(v) + { + }; + THashNode & operator =(const THashNode &other) + { + key = other.key; + val = other.val; + } + K key; + V val; + }; + typedef List * NodePtr; + public: + class const_iterator; + THash() : m_Buckets(NULL), m_numBuckets(0), m_percentUsed(0.0f) + { + _Refactor(); + } + THash(const THash &other) : m_Buckets(new NodePtr[other.m_numBuckets]), + m_numBuckets(other.m_numBuckets), m_percentUsed(other.m_percentUsed) + { + for (size_t i=0; ikey)->val = iter->val; + } + void operator=(const THash &other) + { + clear(); + for (const_iterator iter = other.begin(); iter != other.end(); ++iter) + _FindOrInsert(iter->key)->val = iter->val; + } + + ~THash() + { + _Clear(); + } + void clear() + { + _Clear(); + _Refactor(); + } + size_t GetBuckets() + { + return m_numBuckets; + } + float PercentUsed() + { + return m_percentUsed; + } + V & operator [](const K & key) + { + THashNode *pNode = _FindOrInsert(key); + return pNode->val; + } + private: + void _Clear() + { + typename List::iterator iter, end; + for (size_t i=0; iend(); + iter = m_Buckets[i]->begin(); + while (iter != end) + { + delete (*iter); + iter++; + } + delete m_Buckets[i]; + m_Buckets[i] = NULL; + } + } + if (m_Buckets) + delete [] m_Buckets; + m_Buckets = NULL; + m_numBuckets = 0; + } + public: + template + V & AltFindOrInsert(const U & ukey) + { + size_t place = HashAlt(ukey) % m_numBuckets; + THashNode *pNode = NULL; + if (!m_Buckets[place]) + { + m_Buckets[place] = new List; + pNode = new THashNode(ukey, V()); + m_Buckets[place]->push_back(pNode); + m_percentUsed += (1.0f / (float)m_numBuckets); + } else { + typename List::iterator iter; + for (iter=m_Buckets[place]->begin(); iter!=m_Buckets[place]->end(); iter++) + { + if (CompareAlt(ukey, (*iter)->key) == 0) + { + return (*iter)->val; + } + } + //node does not exist + pNode = new THashNode(ukey, V()); + m_Buckets[place]->push_back(pNode); + } + if (PercentUsed() > 0.75f) + { + _Refactor(); + } + return pNode->val; + } + private: + THashNode *_FindOrInsert(const K & key) + { + size_t place = HashFunction(key) % m_numBuckets; + THashNode *pNode = NULL; + if (!m_Buckets[place]) + { + m_Buckets[place] = new List; + pNode = new THashNode(key, V()); + m_Buckets[place]->push_back(pNode); + m_percentUsed += (1.0f / (float)m_numBuckets); + } else { + typename List::iterator iter; + for (iter=m_Buckets[place]->begin(); iter!=m_Buckets[place]->end(); iter++) + { + if (Compare((*iter)->key, key) == 0) + return (*iter); + } + //node does not exist + pNode = new THashNode(key, V()); + m_Buckets[place]->push_back(pNode); + } + if (PercentUsed() > 0.75f) + { + _Refactor(); + } + return pNode; + } + void _Refactor() + { + m_percentUsed = 0.0f; + if (!m_numBuckets) + { + m_numBuckets = _T_INIT_HASH_SIZE; + m_Buckets = new NodePtr[m_numBuckets]; + for (size_t i=0; i::iterator iter; + size_t place; + THashNode *pHashNode; + NodePtr *temp = new NodePtr[m_numBuckets]; + for (size_t i=0; ibegin(); iter != m_Buckets[i]->end(); iter++) + { + pHashNode = (*iter); + //rehash it with the new bucket filter + place = HashFunction(pHashNode->key) % m_numBuckets; + //add it to the new hash table + if (!temp[place]) + { + temp[place] = new List; + m_percentUsed += (1.0f / (float)m_numBuckets); + } + temp[place]->push_back(pHashNode); + } + //delete that bucket! + delete m_Buckets[i]; + m_Buckets[i] = NULL; + } + } + //reassign bucket table + delete [] m_Buckets; + m_Buckets = temp; + } + } + public: + friend class iterator; + friend class const_iterator; + class iterator + { + friend class THash; + public: + iterator() : curbucket(-1), hash(NULL), end(true) + { + }; + iterator(THash *h) : curbucket(-1), hash(h), end(false) + { + if (!h->m_Buckets) + end = true; + else + _Inc(); + }; + //pre increment + iterator & operator++() + { + _Inc(); + return *this; + } + //post increment + iterator operator++(int) + { + iterator old(*this); + _Inc(); + return old; + } + const THashNode & operator * () const + { + return *(*iter); + } + THashNode & operator * () + { + return *(*iter); + } + const THashNode * operator ->() const + { + return (*iter); + } + THashNode * operator ->() + { + return (*iter); + } + bool operator ==(const iterator &where) const + { + if (where.hash == this->hash + && where.end == this->end + && + (this->end || + ((where.curbucket == this->curbucket) + && (where.iter == iter)) + )) + return true; + return false; + } + bool operator !=(const iterator &where) const + { + return !( (*this) == where ); + } + + void erase() + { + if (end || !hash || curbucket < 0 || curbucket >= static_cast(hash->m_numBuckets)) + return; + + // Remove this element and move to the next one + iterator tmp = *this; + ++tmp; + delete (*iter); + hash->m_Buckets[curbucket]->erase(iter); + *this = tmp; + + // :TODO: Maybe refactor to a lower size if required + } + private: + void _Inc() + { + if (end || !hash || curbucket >= static_cast(hash->m_numBuckets)) + return; + if (curbucket < 0) + { + for (int i=0; i<(int)hash->m_numBuckets; i++) + { + if (hash->m_Buckets[i]) + { + iter = hash->m_Buckets[i]->begin(); + if (iter == hash->m_Buckets[i]->end()) + continue; + curbucket = i; + break; + } + } + if (curbucket < 0) + end = true; + } else { + if (iter != hash->m_Buckets[curbucket]->end()) + iter++; + if (iter == hash->m_Buckets[curbucket]->end()) + { + int oldbucket = curbucket; + for (int i=curbucket+1; i<(int)hash->m_numBuckets; i++) + { + if (hash->m_Buckets[i]) + { + iter = hash->m_Buckets[i]->begin(); + if (iter == hash->m_Buckets[i]->end()) + continue; + curbucket = i; + break; + } + } + if (curbucket == oldbucket) + end = true; + } + } + } + private: + int curbucket; + typename SourceHook::List::iterator iter; + THash *hash; + bool end; + }; + class const_iterator + { + friend class THash; + public: + const_iterator() : curbucket(-1), hash(NULL), end(true) + { + }; + const_iterator(const THash *h) : curbucket(-1), hash(h), end(false) + { + if (!h->m_Buckets) + end = true; + else + _Inc(); + }; + //pre increment + const_iterator & operator++() + { + _Inc(); + return *this; + } + //post increment + const_iterator operator++(int) + { + iterator old(*this); + _Inc(); + return old; + } + const THashNode & operator * () const + { + return *(*iter); + } + const THashNode * operator ->() const + { + return (*iter); + } + bool operator ==(const const_iterator &where) const + { + if (where.hash == this->hash + && where.end == this->end + && + (this->end || + ((where.curbucket == this->curbucket) + && (where.iter == iter)) + )) + return true; + return false; + } + bool operator !=(const const_iterator &where) const + { + return !( (*this) == where ); + } + private: + void _Inc() + { + if (end || !hash || curbucket >= static_cast(hash->m_numBuckets)) + return; + if (curbucket < 0) + { + for (int i=0; i<(int)hash->m_numBuckets; i++) + { + if (hash->m_Buckets[i]) + { + iter = hash->m_Buckets[i]->begin(); + if (iter == hash->m_Buckets[i]->end()) + continue; + curbucket = i; + break; + } + } + if (curbucket < 0) + end = true; + } else { + if (iter != hash->m_Buckets[curbucket]->end()) + iter++; + if (iter == hash->m_Buckets[curbucket]->end()) + { + int oldbucket = curbucket; + for (int i=curbucket+1; i<(int)hash->m_numBuckets; i++) + { + if (hash->m_Buckets[i]) + { + iter = hash->m_Buckets[i]->begin(); + if (iter == hash->m_Buckets[i]->end()) + continue; + curbucket = i; + break; + } + } + if (curbucket == oldbucket) + end = true; + } + } + } + private: + int curbucket; + typename SourceHook::List::iterator iter; + const THash *hash; + bool end; + }; + public: + iterator begin() + { + return iterator(this); + } + iterator end() + { + iterator iter; + iter.hash = this; + return iter; + } + + const_iterator begin() const + { + return const_iterator(this); + } + const_iterator end() const + { + const_iterator iter; + iter.hash = this; + return iter; + } + + template + iterator find(const U & u) const + { + iterator b = begin(); + iterator e = end(); + for (iterator iter = b; iter != e; iter++) + { + if ( (*iter).key == u ) + return iter; + } + return end(); + } + template + iterator find(const U & u) + { + iterator b = begin(); + iterator e = end(); + for (iterator iter = b; iter != e; iter++) + { + if ( (*iter).key == u ) + return iter; + } + return end(); + } + template + iterator FindAlt(const U & u) + { + iterator b = begin(); + iterator e = end(); + for (iterator iter = b; iter != e; iter++) + { + if (CompareAlt(u, (*iter).key) == 0) + { + return iter; + } + } + return e; + } + iterator erase(iterator where) + { + where.erase(); + return where; + } + template + void erase(const U & u) + { + iterator iter = find(u); + if (iter == end()) + return; + iter.erase(); + } + private: + NodePtr *m_Buckets; + size_t m_numBuckets; + float m_percentUsed; + }; +}; + +#endif //_INCLUDE_SH_TINYHASH_H_ diff --git a/utils/mmsource/core-legacy/sourcehook/sh_vector.h b/utils/mmsource/core-legacy/sourcehook/sh_vector.h new file mode 100644 index 00000000..34383ae3 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/sh_vector.h @@ -0,0 +1,519 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2008 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +#ifndef __CVECTOR_H__ +#define __CVECTOR_H__ + +#include + +//This file originally from AMX Mod X +namespace SourceHook +{ +// Vector +template class CVector +{ + bool Grow(size_t amount) + { + // automatic grow + size_t newSize = m_Size * 2; + + if (newSize == 0) + { + newSize = 8; + } + + while (m_CurrentUsedSize + amount > newSize) + { + newSize *= 2; + } + + T *newData = new T[newSize]; + + if (m_Data) + { + for (size_t i=0; i= m_Size) + { + return Grow(amount); + } + else + { + return true; + } + } + + bool ChangeSize(size_t size) + { + // change size + if (size == m_Size) + { + return true; + } + + if (!size) + { + if (m_Data) + { + delete [] m_Data; + m_Data = NULL; + m_Size = 0; + } + return true; + } + + T *newData = new T[size]; + + if (m_Data) + { + size_t end = (m_CurrentUsedSize < size) ? (m_CurrentUsedSize) : size; + for (size_t i=0; i m_Size) + { + m_CurrentUsedSize = m_Size; + } + + return true; + } + + void FreeMemIfPossible() + { + if (!m_Data) + { + return; + } + + if (!m_CurrentUsedSize) + { + ChangeSize(0); + return; + } + + size_t newSize = m_Size; + while (m_CurrentUsedSize <= newSize / 2) + { + newSize /= 2; + } + + if (newSize != m_Size) + { + ChangeSize(newSize); + } + } +protected: + T *m_Data; + size_t m_Size; + size_t m_CurrentUsedSize; +public: + class iterator + { + protected: + T *m_Ptr; + public: + // constructors / destructors + iterator() + { + m_Ptr = NULL; + } + + iterator(T * ptr) + { + m_Ptr = ptr; + } + + // member functions + T * base() + { + return m_Ptr; + } + + const T * base() const + { + return m_Ptr; + } + + // operators + T & operator*() + { + return *m_Ptr; + } + + T * operator->() + { + return m_Ptr; + } + + iterator & operator++() // preincrement + { + ++m_Ptr; + return (*this); + } + + iterator operator++(int) // postincrement + { + iterator tmp = *this; + ++m_Ptr; + return tmp; + } + + iterator & operator--() // predecrement + { + --m_Ptr; + return (*this); + } + + iterator operator--(int) // postdecrememnt + { + iterator tmp = *this; + --m_Ptr; + return tmp; + } + + bool operator==(T * right) const + { + return (m_Ptr == right); + } + + bool operator==(const iterator & right) const + { + return (m_Ptr == right.m_Ptr); + } + + bool operator!=(T * right) const + { + return (m_Ptr != right); + } + + bool operator!=(const iterator & right) const + { + return (m_Ptr != right.m_Ptr); + } + + iterator & operator+=(size_t offset) + { + m_Ptr += offset; + return (*this); + } + + iterator & operator-=(size_t offset) + { + m_Ptr -= offset; + return (*this); + } + + iterator operator+(size_t offset) const + { + iterator tmp(*this); + tmp.m_Ptr += offset; + return tmp; + } + + iterator operator-(size_t offset) const + { + iterator tmp(*this); + tmp.m_Ptr -= offset; + return tmp; + } + + T & operator[](size_t offset) + { + return (*(*this + offset)); + } + + const T & operator[](size_t offset) const + { + return (*(*this + offset)); + } + + bool operator<(const iterator & right) const + { + return m_Ptr < right.m_Ptr; + } + + bool operator>(const iterator & right) const + { + return m_Ptr > right.m_Ptr; + } + + bool operator<=(const iterator & right) const + { + return m_Ptr <= right.m_Ptr; + } + + bool operator>=(const iterator & right) const + { + return m_Ptr >= right.m_Ptr; + } + + size_t operator-(const iterator & right) const + { + return m_Ptr - right.m_Ptr; + } + }; + + // constructors / destructors + CVector() + { + m_Size = 0; + m_CurrentUsedSize = 0; + m_Data = NULL; + } + + CVector(const CVector & other) + { + // copy data + m_Data = new T [other.m_CurrentUsedSize]; + m_Size = other.m_CurrentUsedSize; + m_CurrentUsedSize = other.m_CurrentUsedSize; + for (size_t i=0; i() + { + clear(); + } + + CVector & operator =(const CVector & other) + { + clear(); + ChangeSize(other.size()); + m_CurrentUsedSize = other.size(); + for (size_t i=0; i m_CurrentUsedSize) + assert(0); + return iterator(m_Data + pos); + } + + bool reserve(size_t newSize) + { + if (newSize > m_Size) + return ChangeSize(newSize); + return true; + } + + bool push_back(const T & elem) + { + if (!GrowIfNeeded(1)) + { + return false; + } + + m_Data[m_CurrentUsedSize++] = elem; + + return true; + } + + void pop_back() + { + --m_CurrentUsedSize; + if (m_CurrentUsedSize < 0) + m_CurrentUsedSize = 0; + + FreeMemIfPossible(); + } + + bool resize(size_t newSize) + { + return resize(newSize, T()); + } + + bool resize(size_t newSize, T defval) + { + if (!ChangeSize(newSize)) + return false; + for (size_t i = m_CurrentUsedSize; i < newSize; ++i) + m_Data[i] = defval; + m_CurrentUsedSize = newSize; + return true; + } + + bool empty() const + { + return (m_CurrentUsedSize == 0); + } + + T & at(size_t pos) + { + if (pos > m_CurrentUsedSize) + { + assert(0); + } + return m_Data[pos]; + } + + const T & at(size_t pos) const + { + if (pos > m_CurrentUsedSize) + { + assert(0); + } + return m_Data[pos]; + } + + T & operator[](size_t pos) + { + return at(pos); + } + + const T & operator[](size_t pos) const + { + return at(pos); + } + + T & front() + { + if (m_CurrentUsedSize < 1) + { + assert(0); + } + return m_Data[0]; + } + + const T & front() const + { + if (m_CurrentUsedSize < 1) + { + assert(0); + } + return m_Data[0]; + } + + T & back() + { + if (m_CurrentUsedSize < 1) + { + assert(0); + } + return m_Data[m_CurrentUsedSize - 1]; + } + + const T & back() const + { + if (m_CurrentUsedSize < 1) + { + assert(0); + } + return m_Data[m_CurrentUsedSize - 1]; + } + + iterator insert(iterator where, const T & value) + { + // validate iter + if (where < m_Data || where > (m_Data + m_CurrentUsedSize)) + return iterator(0); + + size_t ofs = where - begin(); + + if (!GrowIfNeeded(1)) + { + return iterator(0); + } + + ++m_CurrentUsedSize; + + where = begin() + ofs; + + // Move subsequent entries + for (T *ptr = m_Data + m_CurrentUsedSize - 2; ptr >= where.base(); --ptr) + *(ptr + 1) = *ptr; + + *where.base() = value; + + return where; + } + + iterator erase(iterator where) + { + // validate iter + if (where < m_Data || where >= (m_Data + m_CurrentUsedSize)) + return iterator(0); + + size_t ofs = where - begin(); + + if (m_CurrentUsedSize > 1) + { + // move + T *theend = m_Data + m_CurrentUsedSize; + for (T *ptr = where.base() + 1; ptr < theend; ++ptr) + *(ptr - 1) = *ptr; + } + + --m_CurrentUsedSize; + + FreeMemIfPossible(); + + return begin() + ofs; + } + + void clear() + { + m_Size = 0; + m_CurrentUsedSize = 0; + if (m_Data) + { + delete [] m_Data; + m_Data = NULL; + } + } +}; +}; //namespace SourceHook + +#endif // __CVECTOR_H__ diff --git a/utils/mmsource/core-legacy/sourcehook/sourcehook.cpp b/utils/mmsource/core-legacy/sourcehook/sourcehook.cpp new file mode 100644 index 00000000..6a713fee --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/sourcehook.cpp @@ -0,0 +1,1463 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2007 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* Contributors: Scott "Damaged Soul" Ehlert +* ============================ +*/ + +/** + * @file sourcehook.cpp + * @brief Contains the implementation of the SourceHook API +*/ + +#if defined __GNUC__ +#include +#endif + +#include "sourcehook_impl.h" +#include "sh_memory.h" + +namespace SourceHook +{ + template<> + int HashFunction(const int & k) + { + return k; + } + template<> + int Compare(const int & k1, const int & k2) + { + if (k1 == k2) + return 0; + if (k1 > k2) + return 1; + if (k1 < k2) + return -1; + return 0; + } + CSourceHookImpl::CSourceHookImpl() : m_OneIgnore(NULL), m_IgnoreActive(false) + { + } + CSourceHookImpl::~CSourceHookImpl() + { + } + + int CSourceHookImpl::GetIfaceVersion() + { + return SH_IFACE_VERSION; + } + + int CSourceHookImpl::GetImplVersion() + { + return SH_IMPL_VERSION; + } + + bool CSourceHookImpl::IsPluginInUse(Plugin plug) + { + // Iterate through all hook managers which are in this plugin + // Iterate through their vfnptrs, ifaces, hooks + // If a hook from an other plugin is found, return true + // Return false otherwise +#define TMP_CHECK_LIST(name) \ + for (hook_iter = iface_iter->name.m_List.begin(); hook_iter != iface_iter->name.m_List.end(); ++hook_iter) \ + if (hook_iter->plug == plug) \ + return true; + + for (HookManContList::iterator hmcl_iter = m_HookMans.begin(); + hmcl_iter != m_HookMans.end(); ++hmcl_iter) + { + for (CHookManagerContainer::iterator hmil_iter = hmcl_iter->begin(); + hmil_iter != hmcl_iter->end(); ++hmil_iter) + { + if (hmil_iter->m_Plug != plug) + continue; + for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->m_VfnPtrs.begin(); + vfnptr_iter != hmil_iter->m_VfnPtrs.end(); ++vfnptr_iter) + { + for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin(); + iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter) + { + List::iterator hook_iter; + TMP_CHECK_LIST(m_PreHooks); + TMP_CHECK_LIST(m_PostHooks); + } + } + } + } + +#undef TMP_CHECK_LIST + return false; + } + + void CSourceHookImpl::UnloadPlugin(Plugin plug) + { + // 1) Manually remove all hooks by this plugin + // 2) Manually remove all hook mans by this plugin + + List hookstoremove; + List hookmanstoremove; + HookManInfoList::iterator hmil_iter; + +#define TMP_CHECK_LIST(name, ispost) \ + for (hook_iter = iface_iter->name.m_List.begin(); hook_iter != iface_iter->name.m_List.end(); ++hook_iter) \ + if (hook_iter->plug == plug) \ + hookstoremove.push_back(RemoveHookInfo(hook_iter->plug, iface_iter->m_Ptr, \ + hook_iter->thisptr_offs, hmil_iter->m_Func, hook_iter->handler, ispost)); \ + + for (HookManContList::iterator hmcl_iter = m_HookMans.begin(); + hmcl_iter != m_HookMans.end(); ++hmcl_iter) + { + for (CHookManagerContainer::iterator hmil_iter = hmcl_iter->begin(); + hmil_iter != hmcl_iter->end(); ++hmil_iter) + { + if (hmil_iter->m_Plug == plug) + hookmanstoremove.push_back(RemoveHookManInfo(plug, hmil_iter->m_Func)); + + for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->m_VfnPtrs.begin(); + vfnptr_iter != hmil_iter->m_VfnPtrs.end(); ++vfnptr_iter) + { + for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin(); + iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter) + { + List::iterator hook_iter; + TMP_CHECK_LIST(m_PreHooks, false); + TMP_CHECK_LIST(m_PostHooks, true); + } + } + } + } +#undef TMP_CHECK_LIST + + for (List::iterator rmiter = hookstoremove.begin(); rmiter != hookstoremove.end(); ++rmiter) + RemoveHook(*rmiter); + + for (List::iterator rmiter = hookmanstoremove.begin(); rmiter != hookmanstoremove.end(); ++rmiter) + RemoveHookManager(*rmiter); + } + + void CSourceHookImpl::RemoveHookManager(Plugin plug, HookManagerPubFunc pubFunc) + { + // Moo! + + CHookManagerInfo tmp; + if (pubFunc(HA_GetInfo, &tmp) != 0) + return; + + + HookManContList::iterator hmcl_iter = m_HookMans.find( + CHookManagerContainer::HMCI(tmp.m_Proto, tmp.m_VtblOffs, tmp.m_VtblIdx)); + + if (hmcl_iter == m_HookMans.end()) + { + // Moo? + return; + } + + CHookManagerContainer::iterator hmil_iter = hmcl_iter->find( + CHookManagerInfo::Descriptor(plug, pubFunc)); + + if (hmil_iter == hmcl_iter->end()) + { + // Moo? + return; + } + + bool stillInUse = false; + List hookstoremove; + + // Iterate through all of the hook manager's hooks. Remove all hooks from the hookman's plugin. +#define TMP_CHECK_LIST(name, ispost) \ + for (hook_iter = iface_iter->name.m_List.begin(); hook_iter != iface_iter->name.m_List.end(); ++hook_iter) \ + if (hook_iter->plug == plug) \ + hookstoremove.push_back(RemoveHookInfo(hook_iter->plug, iface_iter->m_Ptr, \ + hook_iter->thisptr_offs, hmil_iter->m_Func, hook_iter->handler, ispost)); \ + else \ + stillInUse = true; \ + + for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->m_VfnPtrs.begin(); + vfnptr_iter != hmil_iter->m_VfnPtrs.end(); ++vfnptr_iter) + { + for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin(); + iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter) + { + List::iterator hook_iter; + TMP_CHECK_LIST(m_PreHooks, false); + TMP_CHECK_LIST(m_PostHooks, true); + } + } +#undef TMP_CHECK_LIST + + for (List::iterator rmiter = hookstoremove.begin(); rmiter != hookstoremove.end(); ++rmiter) + RemoveHook(*rmiter); + + CHookManagerInfo info = *hmil_iter; + + // Unlink the hook manager from the list + hmcl_iter->erase(hmil_iter); + + // If there were any hooks from other plugins, find a new suitable hook manager. + if (stillInUse) + { + // Find a suitable hook manager in an other plugin + hmil_iter = hmcl_iter->begin(); + + // This should _never_ happen. + // If there is a hook from an other plugin, the plugin must have provided a hook manager as well. + SH_ASSERT(hmil_iter != hmcl_iter->end(), + ("Could not find a suitable hook manager in an other plugin!")); + + // AddHook should make sure that every plugin only has _one_ hook manager for _one_ proto/vi/vo + SH_ASSERT(hmil_iter->m_Plug != plug, ("New hook manager from same plugin!")); + + // The first hook manager should be always used - so the new hook manager has to be empty + SH_ASSERT(hmil_iter->m_VfnPtrs.empty(), ("New hook manager not empty!")); + + // Move the vfnptrs from the old hook manager to the new one + hmil_iter->m_VfnPtrs = info.m_VfnPtrs; + + // Unregister the old one, register the new one + info.m_Func(HA_Unregister, NULL); + hmil_iter->m_Func(HA_Register, &(*hmil_iter)); + + // Go through all vfnptrs in this hookman and patch them to point to the new manager's handler! + // or whatever + for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->m_VfnPtrs.begin(); + vfnptr_iter != hmil_iter->m_VfnPtrs.end(); ++vfnptr_iter) + { + // And DEREFERENCE newHookMan->m_HookfuncVfnptr! + // otherwise it will be executing the vtable... had to find out the hard way + *reinterpret_cast(vfnptr_iter->m_Ptr) = *reinterpret_cast(hmil_iter->m_HookfuncVfnptr); + } + } + } + + void CSourceHookImpl::RemoveHookManager(RemoveHookManInfo info) + { + RemoveHookManager(info.plug, info.hookman); + } + + void CSourceHookImpl::CompleteShutdown() + { + // Remove all hooks + + List hookstoremove; + +#define TMP_CHECK_LIST(name, ispost) \ + for (hook_iter = iface_iter->name.m_List.begin(); hook_iter != iface_iter->name.m_List.end(); ++hook_iter) \ + hookstoremove.push_back(RemoveHookInfo(hook_iter->plug, iface_iter->m_Ptr, \ + hook_iter->thisptr_offs, hmil_iter->m_Func, hook_iter->handler, ispost)) + for (HookManContList::iterator hmcl_iter = m_HookMans.begin(); + hmcl_iter != m_HookMans.end(); ++hmcl_iter) + { + for (CHookManagerContainer::iterator hmil_iter = hmcl_iter->begin(); + hmil_iter != hmcl_iter->end(); ++hmil_iter) + { + for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->m_VfnPtrs.begin(); + vfnptr_iter != hmil_iter->m_VfnPtrs.end(); ++vfnptr_iter) + { + for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin(); + iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter) + { + List::iterator hook_iter; + TMP_CHECK_LIST(m_PreHooks, false); + TMP_CHECK_LIST(m_PostHooks, true); + } + } + } + } +#undef TMP_CHECK_LIST + + for (List::iterator rmiter = hookstoremove.begin(); rmiter != hookstoremove.end(); ++rmiter) + RemoveHook(*rmiter); + + m_HookMans.clear(); + } + + + bool CSourceHookImpl::AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) + { + return AddHookNew(plug, Hook_Normal, iface, thisptr_offs, myHookMan, handler, post) != 0 ? true : false; + } + + int CSourceHookImpl::AddHookNew(Plugin plug, AddHookMode mode, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, + ISHDelegate *handler, bool post) + { + void *adjustediface = NULL; + void **cur_vtptr = NULL; + void *cur_vfnptr = NULL; + + if (mode != Hook_Normal && mode != Hook_VP && mode != Hook_DVP) + return 0; + + // 1) Get info about the hook manager + CHookManagerInfo tmp; + if (myHookMan(HA_GetInfo, &tmp) != 0) + return 0; + + tmp.m_Func = myHookMan; + tmp.m_Plug = plug; + + CHookManagerContainer::HMCI hmci(tmp.m_Proto, tmp.m_VtblOffs, tmp.m_VtblIdx); + + // Add the container if not already added + HookManContList::iterator hmcl_iter = m_HookMans.find(hmci); + if (hmcl_iter == m_HookMans.end()) + { + m_HookMans.push_back(CHookManagerContainer(hmci)); + hmcl_iter = m_HookMans.end(); + --hmcl_iter; + } + + hmcl_iter->AddHookManager(plug, tmp); + + CHookManagerContainer::iterator hookman = hmcl_iter->begin(); + SH_ASSERT(hookman != hmcl_iter->end(), ("No hookman found - but we've just added one!")); + + // Check whether any other container holds a hook manager which holds this vfnptr + // If yes, it means that the two are incompatible, so return false. + for (HookManContList::iterator hmcl_iter2 = m_HookMans.begin(); + hmcl_iter2 != m_HookMans.end(); ++hmcl_iter2) + { + if (hmcl_iter2 != hmcl_iter) + { + for (CHookManagerContainer::iterator hmil_iter = hmcl_iter2->begin(); + hmil_iter != hmcl_iter2->end(); ++hmil_iter) + { + if (hmil_iter->m_VfnPtrs.find(cur_vfnptr) != hmil_iter->m_VfnPtrs.end()) + return 0; + } + } + } + + // Tell it to store the pointer if it's not already active + if (hookman->m_VfnPtrs.empty()) + hookman->m_Func(HA_Register, &(*hookman)); + + + // find vfnptr + if (mode == Hook_Normal || mode == Hook_VP) + { + adjustediface = reinterpret_cast(reinterpret_cast(iface) + thisptr_offs); + + cur_vtptr = *reinterpret_cast( + reinterpret_cast(adjustediface) + tmp.m_VtblOffs); + cur_vfnptr = reinterpret_cast(cur_vtptr + tmp.m_VtblIdx); + + // For Hook_VP, adjustediface will be set to NULL later + // because we first have to patch callclasses (callclasses are deprecated but left in for backwards compat) + } + else if (mode == Hook_DVP) + { + adjustediface = NULL; + + cur_vtptr = reinterpret_cast(iface); + cur_vfnptr = cur_vtptr + tmp.m_VtblIdx; + } + + CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.find(cur_vfnptr); + + if (vfnptr_iter == hookman->m_VfnPtrs.end()) + { + // Add a new one + CVfnPtr vfp(cur_vfnptr, &m_OneIgnore); + + // Alter vtable entry + if (!MakePageWritable(cur_vfnptr)) + return 0; + + *reinterpret_cast(cur_vfnptr) = *reinterpret_cast(hookman->m_HookfuncVfnptr); + + hookman->m_VfnPtrs.push_back(vfp); + + // Make vfnptr_iter point to the new element + vfnptr_iter = hookman->m_VfnPtrs.end(); + --vfnptr_iter; + + // Now that it is done, check whether we have to update any callclasses + ApplyCallClassPatches(adjustediface, tmp.m_VtblOffs, tmp.m_VtblIdx, vfp.m_OrigEntry); + } + + // If it's a VP hook, set adjustediface to NULL now ( see the comments at the beginning of sourcehook_impl.h ) + if (mode == Hook_VP) + adjustediface = NULL; + + CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.find(adjustediface); + if (iface_iter == vfnptr_iter->m_Ifaces.end()) + { + // Add a new one + vfnptr_iter->m_Ifaces.push_back(CIface(adjustediface)); + + // Make iface_iter point to the new element + iface_iter = vfnptr_iter->m_Ifaces.end(); + --iface_iter; + + // If this is a VP-Hook-NULL interface, go through all other interfaces of this vfnptr and tell them! + if (adjustediface == NULL) + { + for (CVfnPtr::IfaceListIter iface_iter2 = vfnptr_iter->m_Ifaces.begin(); + iface_iter2 != vfnptr_iter->m_Ifaces.end(); ++iface_iter2) + { + if (*iface_iter2 != NULL) + { + iface_iter2->m_PreHooks.SetVPList(&iface_iter->m_PreHooks.m_List); + iface_iter2->m_PostHooks.SetVPList(&iface_iter->m_PostHooks.m_List); + } + } + } + else + { + // If this is a new non-VP-Hook-NULL interface, look for a non-VP-Hook-NULL interface! + for (CVfnPtr::IfaceListIter iface_iter2 = vfnptr_iter->m_Ifaces.begin(); + iface_iter2 != vfnptr_iter->m_Ifaces.end(); ++iface_iter2) + { + if (*iface_iter2 == NULL) + { + iface_iter->m_PreHooks.SetVPList(&iface_iter2->m_PreHooks.m_List); + iface_iter->m_PostHooks.SetVPList(&iface_iter2->m_PostHooks.m_List); + break; // There can only be one! + } + } + } + } + + // Add the hook + HookInfo hookinfo; + hookinfo.handler = handler; + hookinfo.plug = plug; + hookinfo.paused = false; + hookinfo.thisptr_offs = thisptr_offs; + hookinfo.hookid = m_HookIDMan.New(tmp.m_Proto, tmp.m_VtblOffs, tmp.m_VtblIdx, cur_vfnptr, + adjustediface, plug, thisptr_offs, handler, post); + + if (post) + iface_iter->m_PostHooks.m_List.push_back(hookinfo); + else + iface_iter->m_PreHooks.m_List.push_back(hookinfo); + + return hookinfo.hookid; + } + + bool CSourceHookImpl::RemoveHookByID(Plugin plug, int hookid) + { + const CHookIDManager::Entry *hentry; + + hentry = m_HookIDMan.QueryHook(hookid); + if (!hentry) + { + // hookid doesn't exist ! + return false; + } + + HookManContList::iterator hmcl_iter = m_HookMans.find( + CHookManagerContainer::HMCI(hentry->proto.GetProto(), hentry->vtbl_offs, hentry->vtbl_idx)); + if (hmcl_iter == m_HookMans.end() || hmcl_iter->empty()) + return false; + CHookManagerContainer::iterator hookman = hmcl_iter->begin(); + + // Find vfnptr + CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.find(hentry->vfnptr); + if (vfnptr_iter == hookman->m_VfnPtrs.end()) + return false; + + // Find iface + CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.find(hentry->adjustediface); + if (iface_iter == vfnptr_iter->m_Ifaces.end()) + return false; + + // Find hook + List &hooks = hentry->post ? iface_iter->m_PostHooks.m_List : iface_iter->m_PreHooks.m_List; + + List::iterator hookiter = hooks.find(hookid); + if (hookiter == hooks.end()) + return false; + + hookiter->handler->DeleteThis(); + + // Move all iterators pointing at this + List::iterator oldhookiter = hookiter; + hookiter = hooks.erase(hookiter); + List::iterator newhookiter = hookiter; + --newhookiter; // The hook loop will ++ it then + CHookList::CIter *pItIter; + + for (pItIter = iface_iter->m_PreHooks.m_UsedIters; pItIter; pItIter = pItIter->m_pNext) + if (pItIter->m_Iter == oldhookiter) + pItIter->m_Iter = newhookiter; + + // If this is VP-Hook-NULL interface, also check all other interfaces of this vfnptr + if (*iface_iter == NULL) + { + for (CVfnPtr::IfaceListIter iface_iter2 = vfnptr_iter->m_Ifaces.begin(); + iface_iter2 != vfnptr_iter->m_Ifaces.end(); ++iface_iter2) + { + if (*iface_iter2 != NULL) + { + for (pItIter = iface_iter2->m_PreHooks.m_UsedIters; pItIter; pItIter = pItIter->m_pNext) + if (pItIter->m_Iter == oldhookiter) + pItIter->m_Iter = newhookiter; + } + } + } + + if (iface_iter->m_PostHooks.m_List.empty() && iface_iter->m_PreHooks.m_List.empty()) + { + // If this is a VP-Hook-NULL interface, go through all other interfaces of this vfnptr and tell them! + if (*iface_iter == NULL) + { + for (CVfnPtr::IfaceListIter iface_iter2 = vfnptr_iter->m_Ifaces.begin(); + iface_iter2 != vfnptr_iter->m_Ifaces.end(); ++iface_iter2) + { + if (iface_iter2->m_Ptr != NULL) + { + iface_iter2->m_PreHooks.ClearVPList(); + iface_iter2->m_PostHooks.ClearVPList(); + } + } + } + + + // There are no hooks on this iface anymore... + for (HookLoopInfoStack::iterator hli_iter = m_HLIStack.begin(); + hli_iter != m_HLIStack.end(); ++hli_iter) + { + if (hli_iter->pCurIface == static_cast(&(*iface_iter))) + hli_iter->shouldContinue = false; + } + + iface_iter = vfnptr_iter->m_Ifaces.erase(iface_iter); + if (vfnptr_iter->m_Ifaces.empty()) + { + // No ifaces at all -> Deactivate the hook + + // Only patch the vfnptr back if the module is still in memory + // If it's not, do not remove stuff like we did before + // First off we did it wrong (shutdown the whole hookman, uh..) and secondly applications may be + // confused by RemoveHook returning false then (yeah, I know, I made this one up, no one checks for RemoveHook error) + if (ModuleInMemory(reinterpret_cast(vfnptr_iter->m_Ptr), SH_PTRSIZE)) + { + *reinterpret_cast(vfnptr_iter->m_Ptr) = vfnptr_iter->m_OrigEntry; + } + + hookman->m_VfnPtrs.erase(vfnptr_iter); + + // Remove callclass patch + for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter) + if (cciter->m_Ptr == hentry->adjustediface) + cciter->RemoveCallClassPatch(hentry->vtbl_offs, hentry->vtbl_idx); + + if (hookman->m_VfnPtrs.empty()) + { + // Unregister the hook manager + hookman->m_Func(HA_Unregister, NULL); + } + } + } + + // Don't forget to remove the hookid from m_HookIDMan + m_HookIDMan.Remove(hookid); + + return true; + } + + bool CSourceHookImpl::RemoveHook(RemoveHookInfo info) + { + return RemoveHook(info.plug, info.iface, info.thisptr_offs, info.hookman, info.handler, info.post); + } + + bool CSourceHookImpl::RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) + { + // Get info about hook manager and compute adjustediface + CHookManagerInfo tmp; + if (myHookMan(HA_GetInfo, &tmp) != 0) + return false; + + void *adjustediface = reinterpret_cast(reinterpret_cast(iface)+thisptr_offs); + + // Loop through all hooks and remove those which match: + // hookman, vfnptr, iface, plug, adjusted iface, this ptr offs, handler, post + CVector removehooks; + m_HookIDMan.FindAllHooks(removehooks, tmp.m_Proto, tmp.m_VtblOffs, tmp.m_VtblIdx, adjustediface, plug, thisptr_offs, handler, post); + + if (removehooks.empty()) + return false; + + bool status = false; + + for (CVector::iterator iter = removehooks.begin(); iter != removehooks.end(); ++iter) + { + if (RemoveHookByID(plug, *iter)) + status = true; + } + return status; + } + + DeprecatedCallClass *CSourceHookImpl::GetCallClass(void *iface, size_t size) + { + for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter) + { + if (cciter->m_Ptr == iface && cciter->m_ObjSize == size) + { + ++cciter->m_RefCounter; + return &(*cciter); + } + } + + // Make a new one + + CCallClassImpl tmp(iface, size); + ApplyCallClassPatches(tmp); + m_CallClasses.push_back(tmp); + return &m_CallClasses.back(); + } + + void CSourceHookImpl::ReleaseCallClass(DeprecatedCallClass *ptr) + { + Impl_CallClassList::iterator iter = m_CallClasses.find(ptr); + if (iter == m_CallClasses.end()) + return; + --iter->m_RefCounter; + if (iter->m_RefCounter < 1) + m_CallClasses.erase(iter); + } + + void CSourceHookImpl::ApplyCallClassPatches(CCallClassImpl &cc) + { + for (HookManContList::iterator hmcl_iter = m_HookMans.begin(); + hmcl_iter != m_HookMans.end(); ++hmcl_iter) + { + for (CHookManagerContainer::iterator hookman = hmcl_iter->begin(); + hookman != hmcl_iter->end(); ++hookman) + { + for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.begin(); + vfnptr_iter != hookman->m_VfnPtrs.end(); ++vfnptr_iter) + { + for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin(); + iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter) + { + if (iface_iter->m_Ptr >= cc.m_Ptr && + iface_iter->m_Ptr < (reinterpret_cast(cc.m_Ptr) + cc.m_ObjSize)) + { + cc.ApplyCallClassPatch(static_cast(reinterpret_cast(iface_iter->m_Ptr) - + reinterpret_cast(cc.m_Ptr)) + hookman->m_VtblOffs, + hookman->m_VtblIdx, vfnptr_iter->m_OrigEntry); + } + } + } + } + } + } + + void CSourceHookImpl::ApplyCallClassPatches(void *ifaceptr, int vtbl_offs, int vtbl_idx, void *orig_entry) + { + for (Impl_CallClassList::iterator cc_iter = m_CallClasses.begin(); cc_iter != m_CallClasses.end(); + ++cc_iter) + { + if (ifaceptr >= cc_iter->m_Ptr && + ifaceptr < (reinterpret_cast(cc_iter->m_Ptr) + cc_iter->m_ObjSize)) + { + cc_iter->ApplyCallClassPatch(static_cast(reinterpret_cast(ifaceptr) - + reinterpret_cast(cc_iter->m_Ptr)) + vtbl_offs, vtbl_idx, orig_entry); + } + } + } + + void CSourceHookImpl::RemoveCallClassPatches(void *ifaceptr, int vtbl_offs, int vtbl_idx) + { + for (Impl_CallClassList::iterator cc_iter = m_CallClasses.begin(); cc_iter != m_CallClasses.end(); + ++cc_iter) + { + if (ifaceptr >= cc_iter->m_Ptr && + ifaceptr < (reinterpret_cast(cc_iter->m_Ptr) + cc_iter->m_ObjSize)) + { + cc_iter->RemoveCallClassPatch(vtbl_offs, vtbl_idx); + } + } + } + + void CSourceHookImpl::SetPluginPaused(Plugin plug, bool paused) + { + // Go through all hook managers, all interfaces, and set the status of all hooks of this plugin to paused + for (HookManContList::iterator hmcl_iter = m_HookMans.begin(); + hmcl_iter != m_HookMans.end(); ++hmcl_iter) + { + for (CHookManagerContainer::iterator hookmaniter = hmcl_iter->begin(); + hookmaniter != hmcl_iter->end(); ++hookmaniter) + { + for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookmaniter->m_VfnPtrs.begin(); + vfnptr_iter != hookmaniter->m_VfnPtrs.end(); ++vfnptr_iter) + { + for (CVfnPtr::IfaceListIter ifaceiter = vfnptr_iter->m_Ifaces.begin(); + ifaceiter != vfnptr_iter->m_Ifaces.end(); ++ifaceiter) + { + for (List::iterator hookiter = ifaceiter->m_PreHooks.m_List.begin(); + hookiter != ifaceiter->m_PreHooks.m_List.end(); ++hookiter) + if (plug == hookiter->plug) + hookiter->paused = paused; + + for (List::iterator hookiter = ifaceiter->m_PostHooks.m_List.begin(); + hookiter != ifaceiter->m_PostHooks.m_List.end(); ++hookiter) + if (plug == hookiter->plug) + hookiter->paused = paused; + } + } + } + } + } + void CSourceHookImpl::PausePlugin(Plugin plug) + { + SetPluginPaused(plug, true); + } + + void CSourceHookImpl::UnpausePlugin(Plugin plug) + { + SetPluginPaused(plug, false); + } + + void CSourceHookImpl::HookLoopBegin(IIface *pIface) + { + HookLoopInfo hli = {0}; + hli.pCurIface = pIface; + hli.shouldContinue = true; + hli.recall = HookLoopInfo::Recall_No; + + static_cast(pIface)->m_PreHooks.RQFlagReset(); + static_cast(pIface)->m_PostHooks.RQFlagReset(); + + m_HLIStack.push(hli); + } + + void CSourceHookImpl::HookLoopEnd() + { + // When in a post recall... make sure status is high enough so that it returns the orig ret. + if (m_HLIStack.size() > 1 && m_HLIStack.second().recall == HookLoopInfo::Recall_Post2) + *m_HLIStack.front().pStatus = MRES_SUPERCEDE; // THAT'LL TEACH THEM! + m_HLIStack.pop(); + } + + void CSourceHookImpl::SetRes(META_RES res) + { + *m_HLIStack.front().pCurRes = res; + } + + META_RES CSourceHookImpl::GetPrevRes() + { + return *m_HLIStack.front().pPrevRes; + } + + META_RES CSourceHookImpl::GetStatus() + { + return *m_HLIStack.front().pStatus; + } + + const void *CSourceHookImpl::GetOrigRet() + { + // When in a post recall... return the orig ret of the previous hookloop. + if (m_HLIStack.size() > 1 && m_HLIStack.second().recall == HookLoopInfo::Recall_Post2) + return m_HLIStack.second().pOrigRet; + + return m_HLIStack.front().pOrigRet; + } + + const void *CSourceHookImpl::GetOverrideRet() + { + // pOverrideRet is always set since recalls were introduced + // GetOverrideRetPtr was added; a function which always returns pOverrideRet + // so that RETURN_META_VALUE_NEWPARAMS can provide an override result + + // This means that we have to filter GetOverrideRet: + // If the status variable is < MRES_OVERRIDE, return NULL. + + return (*m_HLIStack.front().pStatus < MRES_OVERRIDE) ? + NULL : m_HLIStack.front().pOverrideRet; + } + + void *CSourceHookImpl::GetOverrideRetPtr() + { + // As described in the comment above: always return pOverrideRet + return m_HLIStack.front().pOverrideRet; + } + + void *CSourceHookImpl::GetIfacePtr() + { + return *m_HLIStack.front().pIfacePtrPtr; + } + + void CSourceHookImpl::SetCurResPtr(META_RES *mres) + { + m_HLIStack.front().pCurRes = mres; + } + + void CSourceHookImpl::SetPrevResPtr(META_RES *mres) + { + m_HLIStack.front().pPrevRes = mres; + + // If we're recalling, drag the previous mres value to the new hookfunc + if (m_HLIStack.size() > 1 && m_HLIStack.second().recall) + *mres = *m_HLIStack.second().pPrevRes; + } + + void CSourceHookImpl::SetStatusPtr(META_RES *mres) + { + m_HLIStack.front().pStatus = mres; + + // If we're recalling, drag the previous mres value to the new hookfunc + if (m_HLIStack.size() > 1 && m_HLIStack.second().recall) + *mres = *m_HLIStack.second().pStatus; + } + + void CSourceHookImpl::SetIfacePtrPtr(void **pp) + { + m_HLIStack.front().pIfacePtrPtr = pp; + } + + void CSourceHookImpl::SetOrigRetPtr(const void *ptr) + { + m_HLIStack.front().pOrigRet = ptr; + } + void CSourceHookImpl::SetOverrideRetPtr(void *ptr) + { + m_HLIStack.front().pOverrideRet = ptr; + } + + // New function which does all of the above + more :) + void *CSourceHookImpl::SetupHookLoop(META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr, + void **ifacePtrPtr, const void *origRetPtr, void *overrideRetPtr) + { + HookLoopInfo &hli = m_HLIStack.front(); + hli.pStatus = statusPtr; + hli.pPrevRes = prevResPtr; + hli.pCurRes = curResPtr; + hli.pIfacePtrPtr = ifacePtrPtr; + hli.pOrigRet = origRetPtr; + + // Handle some recall stuff + if (m_HLIStack.size() > 1 && m_HLIStack.second().recall) + { + HookLoopInfo &other = m_HLIStack.second(); + *statusPtr = *other.pStatus; + *prevResPtr = *other.pStatus; + + // When the status is low so there's no override return value and we're in a post recall, + // give it the orig return value as override return value. + if (*statusPtr < MRES_OVERRIDE && other.recall == HookLoopInfo::Recall_Post1) + hli.pOverrideRet = const_cast(other.pOrigRet); + else // Otherwise, transfer override ret normally + hli.pOverrideRet = other.pOverrideRet; + } + else + hli.pOverrideRet = overrideRetPtr; + + // Tell the hook func which override ret ptr to use + return hli.pOverrideRet; + } + + bool CSourceHookImpl::ShouldContinue() + { + // If recall is true, we shall not continue either. + // This is because, if it's true and ShouldContinue is called, it suggests that the + // actual recall is done and that we are back in the original handler which shall return + // immediately. + + // Post-recalls: + // The second element on the stack has recall set to Recall_Post1. + // This means that we want to skip this part and the original function calling thing, so + // we store the status mres value, set status to MRES_SUPERCEDE, and return false. + // We also set the recall flag to Recall_Post2, so the next time the thing calls us, we + // can return true (so that the thing goes into post hooks). + if (m_HLIStack.size() > 1) + { + if (m_HLIStack.second().recall == HookLoopInfo::Recall_Post1) + { + m_HLIStack.front().temporaryStatus = *m_HLIStack.front().pStatus; + *m_HLIStack.front().pStatus = MRES_SUPERCEDE; + m_HLIStack.second().recall = HookLoopInfo::Recall_Post2; + return false; + } + else if (m_HLIStack.second().recall == HookLoopInfo::Recall_Post2) + { + *m_HLIStack.front().pStatus = m_HLIStack.front().temporaryStatus; + return m_HLIStack.front().shouldContinue; + } + } + return m_HLIStack.front().shouldContinue && !m_HLIStack.front().recall; + } + + void CSourceHookImpl::DoRecall() + { + if (!m_HLIStack.empty()) + { + // Also watch out for post recalls! Described at the beginning of sourcehook_impl.h + m_HLIStack.front().recall = + static_cast(m_HLIStack.front().pCurIface)->m_PostHooks.RQFlagGet() ? + HookLoopInfo::Recall_Post1 : HookLoopInfo::Recall_Pre; + + CHookList *mlist = static_cast(m_HLIStack.front().recall == HookLoopInfo::Recall_Pre ? + m_HLIStack.front().pCurIface->GetPreHooks() : m_HLIStack.front().pCurIface->GetPostHooks()); + mlist->m_Recall = true; + + // The hookfunc usually does this, but it won't have a chance to see it, + // so for recalls, we update status here if it's required + if (*m_HLIStack.front().pCurRes > *m_HLIStack.front().pStatus) + *m_HLIStack.front().pStatus = *m_HLIStack.front().pCurRes; + + } + } + + void CSourceHookImpl::SetIgnoreHooks(Plugin plug, void *vfnptr) + { + m_OneIgnore = vfnptr; + } + + void CSourceHookImpl::ResetIgnoreHooks(Plugin plug, void *vfnptr) + { + m_OneIgnore = NULL; + } + + void *CSourceHookImpl::GetOrigVfnPtrEntry(void *vfnptr) + { + for (HookManContList::iterator hmcl_iter = m_HookMans.begin(); + hmcl_iter != m_HookMans.end(); ++hmcl_iter) + { + for (CHookManagerContainer::iterator hookmaniter = hmcl_iter->begin(); + hookmaniter != hmcl_iter->end(); ++hookmaniter) + { + for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookmaniter->m_VfnPtrs.begin(); + vfnptr_iter != hookmaniter->m_VfnPtrs.end(); ++vfnptr_iter) + { + if (vfnptr_iter->m_Ptr == vfnptr) + return vfnptr_iter->m_OrigEntry; + } + } + } + return NULL; + } + + //////////////////////////// + // CCallClassImpl + //////////////////////////// + CSourceHookImpl::CCallClassImpl::CCallClassImpl(void *ptr, size_t size) + : m_Ptr(ptr), m_ObjSize(size), m_RefCounter(1) + { + } + CSourceHookImpl::CCallClassImpl::~CCallClassImpl() + { + } + + void *CSourceHookImpl::CCallClassImpl::GetThisPtr() + { + return m_Ptr; + } + void *CSourceHookImpl::CCallClassImpl::GetOrigFunc(int vtbloffs, int vtblidx) + { + OrigVTables::iterator iter = m_VT.find(vtbloffs); + if (iter != m_VT.end() && iter->val.size() > (size_t)vtblidx) + { + return iter->val[vtblidx]; + } + return NULL; + } + + void CSourceHookImpl::CCallClassImpl::ApplyCallClassPatch(int vtbl_offs, int vtbl_idx, void *orig_entry) + { + OrigFuncs &tmpvec = m_VT[vtbl_offs]; + if (tmpvec.size() <= (size_t)vtbl_idx) + tmpvec.resize(vtbl_idx+1, NULL); + tmpvec[vtbl_idx] = orig_entry; + } + void CSourceHookImpl::CCallClassImpl::RemoveCallClassPatch(int vtbl_offs, int vtbl_idx) + { + OrigVTables::iterator iter = m_VT.find(vtbl_offs); + if (iter != m_VT.end()) + { + if (iter->val.size() > (size_t)vtbl_idx) + { + iter->val[vtbl_idx] = 0; + + OrigFuncs &of = iter->val; + OrigFuncs::iterator lastused = of.end(); + for (OrigFuncs::iterator viter = of.begin(); viter != of.end(); ++viter) + { + if (*viter) + lastused = viter; + } + if (lastused == of.end()) + { + // No used element => Remove the whole vector + m_VT.erase(iter); + return; + } + of.resize(lastused - of.begin() + 1); + } + } + } + + //////////////////////////// + // CHookManagerInfo + //////////////////////////// + CSourceHookImpl::CHookManagerInfo::CHookManagerInfo() : m_HookManVersion(0) + { + } + CSourceHookImpl::CHookManagerInfo::~CHookManagerInfo() + { + } + + IVfnPtr *CSourceHookImpl::CHookManagerInfo::FindVfnPtr(void *vfnptr) + { + VfnPtrListIter iter = m_VfnPtrs.find(vfnptr); + return iter == m_VfnPtrs.end() ? NULL : &(*iter); + } + void CSourceHookImpl::CHookManagerInfo::SetInfo(int vtbl_offs, int vtbl_idx, const char *proto) + { + m_VtblOffs = vtbl_offs; + m_VtblIdx = vtbl_idx; + m_Proto = proto; + } + void CSourceHookImpl::CHookManagerInfo::SetHookfuncVfnptr(void *hookfunc_vfnptr) + { + m_HookfuncVfnptr = hookfunc_vfnptr; + } + void CSourceHookImpl::CHookManagerInfo::SetVersion(int version) + { + m_HookManVersion = version; + } + //////////////////////////// + // CVfnPtr + //////////////////////////// + + + // If you get a crash here, the ptr passed is invalid + // This usually means a SH_DECL_MANUALHOOK* with wrong thisptroffs/vtbloffs/vtblidx + CSourceHookImpl::CVfnPtr::CVfnPtr(void *ptr, void **pOneIgnore) : m_Ptr(ptr), + m_OrigEntry(*reinterpret_cast(ptr)), m_pOneIgnore(pOneIgnore) + { + } + CSourceHookImpl::CVfnPtr::~CVfnPtr() + { + } + + void *CSourceHookImpl::CVfnPtr::GetVfnPtr() + { + return m_Ptr; + } + + void *CSourceHookImpl::CVfnPtr::GetOrigEntry() + { + return m_OrigEntry; + } + + IIface *CSourceHookImpl::CVfnPtr::FindIface(void *ptr) + { + if (m_Ptr == *m_pOneIgnore) + { + *m_pOneIgnore = NULL; // Only once! + return NULL; + } + + IfaceListIter iter = m_Ifaces.find(ptr); + + // If nothing is found, check for a NULL-interface (VP hooks only) + if (iter == m_Ifaces.end()) + { + iter = m_Ifaces.find((void*)0); + return iter == m_Ifaces.end() ? NULL : &(*iter); + } + else + { + return &(*iter); + } + } + + //////////////////////////// + // CIface + //////////////////////////// + CSourceHookImpl::CIface::CIface(void *ptr) : m_Ptr(ptr) + { + } + CSourceHookImpl::CIface::~CIface() + { + } + + void *CSourceHookImpl::CIface::GetPtr() + { + return m_Ptr; + } + + IHookList *CSourceHookImpl::CIface::GetPreHooks() + { + return &m_PreHooks; + } + IHookList *CSourceHookImpl::CIface::GetPostHooks() + { + return &m_PostHooks; + } + + //////////////////////////// + // CHookList + //////////////////////////// + + CSourceHookImpl::CHookList::CHookList() : m_VPList(NULL), m_FreeIters(NULL), m_UsedIters(NULL), + m_Recall(false) + { + } + CSourceHookImpl::CHookList::CHookList(const CHookList &other) : m_VPList(other.m_VPList), m_List(other.m_List), + m_FreeIters(NULL), m_UsedIters(NULL), m_Recall(false) + { + } + + CSourceHookImpl::CHookList::~CHookList() + { + while (m_FreeIters) + { + CIter *iter = m_FreeIters->m_pNext; + delete m_FreeIters; + m_FreeIters = iter; + } + while (m_UsedIters) + { + CIter *iter = m_UsedIters->m_pNext; + delete m_UsedIters; + m_UsedIters = iter; + } + } + IHookList::IIter *CSourceHookImpl::CHookList::GetIter() + { + m_RQFlag = true; + + CIter *ret; + if (m_FreeIters) + { + ret = m_FreeIters; + m_FreeIters = ret->m_pNext; + ret->GoToBegin(); + } + else + { + ret = new CIter(this); + } + + // Muuuh, if we're recalling, it shall be a copy of the last iterator, incremented by one + if (m_Recall && m_UsedIters) + { + ret->Set(m_UsedIters); // m_UsedIters is the last returned and not released iterator + ret->Next(); // Use next instead of directly incrementing its m_Iter: + // skips paused plugins + } + + ret->m_pNext = m_UsedIters; + ret->m_pPrev = NULL; + if (m_UsedIters) + m_UsedIters->m_pPrev = ret; + m_UsedIters = ret; + + m_Recall = false; + + return ret; + } + void CSourceHookImpl::CHookList::ReleaseIter(IIter *pIter) + { + CIter *pIter2 = static_cast(pIter); + + // Unlink from m_UsedIters + + if (pIter2->m_pNext) + pIter2->m_pNext->m_pPrev = pIter2->m_pPrev; + if (pIter2->m_pPrev) + pIter2->m_pPrev->m_pNext = pIter2->m_pNext; + if (pIter2 == m_UsedIters) + m_UsedIters = NULL; + + // Link to m_FreeIters + + pIter2->m_pNext = m_FreeIters; + + m_FreeIters = pIter2; + + // Reset recall state. + m_Recall = false; + } + + void CSourceHookImpl::CHookList::SetVPList(List *newList) + { + m_VPList = newList; + + // Update cached CIter objects + + CIter *pTmp; + pTmp = m_FreeIters; + while (pTmp) + { + pTmp->m_Iter.SetListLeft(m_VPList); + pTmp = pTmp->m_pNext; + } + + pTmp = m_UsedIters; + while (pTmp) + { + pTmp->m_Iter.SetListLeft(m_VPList); + pTmp = pTmp->m_pNext; + } + } + + void CSourceHookImpl::CHookList::ClearVPList() + { + SetVPList(NULL); + } + + CSourceHookImpl::CHookList::CIter::CIter(CHookList *pList) : m_pList(pList), + m_Iter(pList->m_VPList, &m_pList->m_List), m_pNext(NULL) + { + } + CSourceHookImpl::CHookList::CIter::~CIter() + { + } + + void CSourceHookImpl::CHookList::CIter::Set(CIter *pOther) + { + m_Iter = pOther->m_Iter; + } + + void CSourceHookImpl::CHookList::CIter::GoToBegin() + { + m_Iter.GoToBegin(); + SkipPaused(); + } + + bool CSourceHookImpl::CHookList::CIter::End() + { + if (!m_pList) + return false; + return m_Iter.End();; + } + void CSourceHookImpl::CHookList::CIter::Next() + { + if (!m_pList) + return; + ++m_Iter; + SkipPaused(); + } + void CSourceHookImpl::CHookList::CIter::Clear() + { + m_pList = NULL; + } + void CSourceHookImpl::CHookList::CIter::SkipPaused() + { + while (!m_Iter.End() && m_Iter->paused) + ++m_Iter; + } + + ISHDelegate *CSourceHookImpl::CHookList::CIter::Handler() + { + return m_Iter->handler; + } + int CSourceHookImpl::CHookList::CIter::ThisPtrOffs() + { + return m_Iter->thisptr_offs; + } + + ////////////////////////////////////////////////////////////////////////// + // CProto + ////////////////////////////////////////////////////////////////////////// + char *CSourceHookImpl::CProto::DupProto(const char *p) + { + if (!p) + return NULL; + + char *newproto; + if (*p) + { + size_t len = strlen(p); + newproto = new char[len+1]; + memcpy(newproto, p, len+1); + } else { + const ProtoInfo *pi1 = reinterpret_cast(p); + int *ar_copy = new int[pi1->numOfParams + 1]; + for (int i = 0; i <= pi1->numOfParams; i++) + ar_copy[i] = pi1->params[i]; + ProtoInfo *copy = new ProtoInfo(pi1->retTypeSize, pi1->numOfParams, ar_copy); + newproto = reinterpret_cast(copy); + } + + return newproto; + } + + void CSourceHookImpl::CProto::FreeProto(char *prot) + { + if (!prot) + return; + + if (*prot) + { + delete [] prot; + } else { + ProtoInfo *pi = reinterpret_cast(prot); + delete [] pi->params; + delete pi; + } + } + + bool CSourceHookImpl::CProto::Equal(const char *p1, const char *p2) + { + if (!p1 || !p2) + return false; + + if (*p1 && *p2) // Case1: Both old + { + // As in old versions + return strcmp(p1, p2) == 0; + } + else if (!*p1 && !*p2) // Case2: Both new + { + const ProtoInfo *pi1 = reinterpret_cast(p1); + const ProtoInfo *pi2 = reinterpret_cast(p2); + + if (pi1->retTypeSize == pi2->retTypeSize && + pi1->numOfParams == pi2->numOfParams) + { + // params[0] is 0 for "normal" functions and -1 for vararg functions + // params[1] is size of first parameter + // params[2] is size of second parameter ... + for (int i = 0; i <= pi1->numOfParams; ++i) + { + if (pi1->params[i] != pi2->params[i]) + return false; + } + return true; + } + else + { + return false; + } + } + else // Case3: Mixed old/new + { + // Trust the user + return true; + } + } + + + ////////////////////////////////////////////////////////////////////////// + // CHookManagerContainer + ////////////////////////////////////////////////////////////////////////// + void CSourceHookImpl::CHookManagerContainer::AddHookManager(Plugin plug, const CHookManagerInfo &hookman) + { + iterator iter; + // Check whether such a hook manager already exists; if yes, ignore. + for (iter = begin(); iter != end(); ++iter) + { + if (iter->m_Plug == plug && iter->m_Func == hookman.m_Func) + return; + } + + // It doesn't -> add it. Add it to the end of its version group. + for (iter = begin(); iter != end(); ++iter) + { + if (iter->m_HookManVersion < hookman.m_HookManVersion) + break; + } + + bool isBeginning = iter == begin(); + + insert(iter, hookman); + + // If we inserted it at the beginning and if the dam breaks open many years too soon + // and if there is more than one hookman and if the second one isn't empty, transfer + // hooks from second to first + + if (isBeginning && size() > 1) + { + iter = begin(); + iterator second = iter; + ++second; + + if (!second->m_VfnPtrs.empty()) + { + // Move the vfnptrs from the old hook manager to the new one + iter->m_VfnPtrs = second->m_VfnPtrs; + second->m_VfnPtrs.clear(); + + // Unregister the old one, register the new one + second->m_Func(HA_Unregister, NULL); + iter->m_Func(HA_Register, &(*iter)); + + // Go through all vfnptrs in this hookman and patch them to point to the new manager's handler! + // or whatever + for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = iter->m_VfnPtrs.begin(); + vfnptr_iter != iter->m_VfnPtrs.end(); ++vfnptr_iter) + { + // And DEREFERENCE newHookMan->m_HookfuncVfnptr! + // otherwise it will be executing the vtable... had to find out the hard way + *reinterpret_cast(vfnptr_iter->m_Ptr) = *reinterpret_cast(iter->m_HookfuncVfnptr); + } + } + } + } + + ////////////////////////////////////////////////////////////////////////// + // CHookIDManager + ////////////////////////////////////////////////////////////////////////// + CSourceHookImpl::CHookIDManager::CHookIDManager() + { + } + + int CSourceHookImpl::CHookIDManager::New(const CProto &proto, int vtbl_offs, int vtbl_idx, void *vfnptr, + void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post) + { + Entry tmp(proto, vtbl_offs, vtbl_idx, vfnptr, adjustediface, plug, thisptr_offs, handler, post); + + size_t cursize = m_Entries.size(); + for (size_t i = 0; i < cursize; ++i) + { + if (m_Entries[i].isfree) + { + m_Entries[i] = tmp; + return static_cast(i) + 1; + } + } + + m_Entries.push_back(tmp); + return static_cast(m_Entries.size()); // return size() because hookid = id+1 anyway + } + + bool CSourceHookImpl::CHookIDManager::Remove(int hookid) + { + int realid = hookid - 1; + if (realid < 0 || realid >= static_cast(m_Entries.size()) || m_Entries[realid].isfree) + return false; + + m_Entries[realid].isfree = true; + + // :TODO: remove free ids from back sometimes ?? + + return true; + } + + const CSourceHookImpl::CHookIDManager::Entry * CSourceHookImpl::CHookIDManager::QueryHook(int hookid) + { + int realid = hookid - 1; + if (realid < 0 || realid >= static_cast(m_Entries.size()) || m_Entries[realid].isfree) + return NULL; + + return &m_Entries[realid]; + } + + void CSourceHookImpl::CHookIDManager::FindAllHooks(CVector &output, const CProto &proto, int vtbl_offs, + int vtbl_idx, void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post) + { + // oh my god, a lot of parameters... + size_t cursize = m_Entries.size(); + for (size_t i = 0; i < cursize; ++i) + { + if (!m_Entries[i].isfree && m_Entries[i].proto == proto && m_Entries[i].vtbl_offs == vtbl_offs && + m_Entries[i].vtbl_idx == vtbl_idx && m_Entries[i].adjustediface == adjustediface && m_Entries[i].plug == plug && + m_Entries[i].thisptr_offs == thisptr_offs && m_Entries[i].handler->IsEqual(handler) && m_Entries[i].post == post) + { + output.push_back(static_cast(i) + 1); + } + } + } +} diff --git a/utils/mmsource/core-legacy/sourcehook/sourcehook.h b/utils/mmsource/core-legacy/sourcehook/sourcehook.h new file mode 100644 index 00000000..575614b6 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/sourcehook.h @@ -0,0 +1,6547 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2008 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +/** +* @file sourcehook.h +* @brief Contains the public SourceHook API +*/ + +#ifndef __SOURCEHOOK_H__ +#define __SOURCEHOOK_H__ + +// Interface revisions: +// 1 - Initial revision +// 2 - Changed to virtual functions for iterators and all queries +// 3 - Added "hook loop status variable" +// 4 - Reentrant +#define SH_IFACE_VERSION 4 + +// Impl versions: +// ??? +// 4 - addition of hook ids and vp hooks (with them, AddHookNew and RemoveHookNew) +// This is not a SH_IFACE_VERSION change so that old plugins continue working! +// addition of direct vp hooks (new hook mode; from now on AddHookNew checks for +// invalid hookmode -> impl version won't have to change because of things like this) +#define SH_IMPL_VERSION 4 + +// Hookman version: +// 1 - Support for recalls, performance optimisations +#define SH_HOOKMAN_VERSION 1 + +// The value of SH_GLOB_SHPTR has to be a pointer to SourceHook::ISourceHook +// It's used in various macros +#ifndef SH_GLOB_SHPTR +#define SH_GLOB_SHPTR g_SHPtr +#endif + +// Used to identify the current plugin +#ifndef SH_GLOB_PLUGPTR +#define SH_GLOB_PLUGPTR g_PLID +#endif + +#ifdef SH_DEBUG +# include +# include + +# define SH_ASSERT(x, info) \ + do { \ + if (!(x)) \ + { \ + printf("SOURCEHOOK DEBUG ASSERTION FAILED: %s:%u(%s): %s: ", __FILE__, __LINE__, __FUNCTION__, #x); \ + printf info; \ + putchar('\n'); \ + abort(); \ + } \ + } while(0) + +#else +# define SH_ASSERT(x, info) +#endif + +// System +#define SH_SYS_WIN32 1 +#define SH_SYS_LINUX 2 +#define SH_SYS_APPLE 3 + +// OS +#define SH_XP_POSIX 10 +#define SH_XP_WINAPI 20 + +#ifdef _WIN32 +# define SH_SYS SH_SYS_WIN32 +# define SH_XP SH_XP_WINAPI +#elif defined __linux__ +# define SH_SYS SH_SYS_LINUX +# define SH_XP SH_XP_POSIX +#elif defined __APPLE__ +# define SH_SYS SH_SYS_APPLE +# define SH_XP SH_XP_POSIX +#else +# error Unsupported system +#endif + +// Compiler +#define SH_COMP_GCC 1 +#define SH_COMP_MSVC 2 + +#ifdef _MSC_VER +# define SH_COMP SH_COMP_MSVC +#elif defined __GNUC__ +# define SH_COMP SH_COMP_GCC +#else +# error Unsupported compiler +#endif + +#if SH_COMP==SH_COMP_MSVC && _MSC_VER < 1500 +# define vsnprintf _vsnprintf +#endif + +#if SH_SYS != SH_SYS_WIN32 +# include +#endif + +#define SH_PTRSIZE sizeof(void*) + +#include "FastDelegate.h" +#include "sh_memfuncinfo.h" + +// Good old metamod! + +// Flags returned by a plugin's api function. +// NOTE: order is crucial, as greater/less comparisons are made. +enum META_RES +{ + MRES_IGNORED=0, // plugin didn't take any action + MRES_HANDLED, // plugin did something, but real function should still be called + MRES_OVERRIDE, // call real function, but use my return value + MRES_SUPERCEDE // skip real function; use my return value +}; + + +namespace SourceHook +{ + /** + * @brief Specifies the size (in bytes) for the internal buffer of vafmt(printf-like) function handlers + */ + const int STRBUF_LEN=4096; + + /** + * @brief An empty class. No inheritance used. Used for original-function-call hacks + */ + class EmptyClass + { + }; + + /** + * @brief Implicit cast. + */ + template + inline Out implicit_cast(In input) + { + return input; + } + + /** + * @brief A plugin typedef + * + * SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it and every + * plugin has a unique identifier, everything is ok. + * It should also be possible to set it to 0. + */ + typedef int Plugin; + + struct ProtoInfo + { + ProtoInfo(int rtsz, int nop, const int *p) : beginningNull(0), retTypeSize(rtsz), numOfParams(nop), params(p) + { + } + int beginningNull; //!< To distinguish from old protos (which never begin with 0) + int retTypeSize; //!< 0 if void + int numOfParams; //!< number of parameters + const int *params; //!< params[0]=0 (or -1 for vararg), params[1]=size of first param, ... + }; + + /** + * @brief Specifies the actions for hook managers + */ + enum HookManagerAction + { + HA_GetInfo = 0, //!< Store info about the hook manager + HA_Register, //!< Save the IHookManagerInfo pointer for future reference + HA_Unregister //!< Clear the saved pointer + }; + + struct IHookManagerInfo; + + /** + * @brief Pointer to hook manager interface function + * + * A "hook manager" is a the only thing that knows the actual protoype of the function at compile time. + * + * @param ha What the hook manager should do + * @param hi A pointer to IHookManagerInfo + */ + typedef int (*HookManagerPubFunc)(HookManagerAction ha, IHookManagerInfo *hi); + + class ISHDelegate + { + public: + virtual void DeleteThis() = 0; // Ugly, I know + virtual bool IsEqual(ISHDelegate *other) = 0; + }; + + template class CSHDelegate : public ISHDelegate + { + T m_Deleg; + public: + CSHDelegate(T deleg) : m_Deleg(deleg) + { + } + + CSHDelegate(const CSHDelegate &other) : m_Deleg(other.m_Deleg) + { + } + + void DeleteThis() + { + delete this; + } + + bool IsEqual(ISHDelegate *other) + { + return static_cast* >(other)->GetDeleg() == GetDeleg(); + } + + T &GetDeleg() + { + return m_Deleg; + } + }; + + struct IHookList + { + struct IIter + { + virtual bool End() = 0; + virtual void Next() = 0; + virtual ISHDelegate *Handler() = 0; + virtual int ThisPtrOffs() = 0; + }; + virtual IIter *GetIter() = 0; + virtual void ReleaseIter(IIter *pIter) = 0; + }; + + struct IIface + { + virtual void *GetPtr() = 0; + virtual IHookList *GetPreHooks() = 0; + virtual IHookList *GetPostHooks() = 0; + }; + + struct IVfnPtr + { + virtual void *GetVfnPtr() = 0; + virtual void *GetOrigEntry() = 0; + + virtual IIface *FindIface(void *ptr) = 0; + }; + + struct IHookManagerInfo + { + virtual IVfnPtr *FindVfnPtr(void *vfnptr) = 0; + + virtual void SetInfo(int vtbloffs, int vtblidx, const char *proto) = 0; + virtual void SetHookfuncVfnptr(void *hookfunc_vfnptr) = 0; + + // Added 23.12.2005 (yup! I'm coding RIGHT BEFORE CHRISTMAS!) + // If the hookman doesn't set this, it defaults 0 + // SourceHook prefers hookmans with higher version numbers + virtual void SetVersion(int version) = 0; + }; + + class AutoHookIter + { + IHookList *m_pList; + IHookList::IIter *m_pIter; + public: + AutoHookIter(IHookList *pList) + : m_pList(pList), m_pIter(pList->GetIter()) + { + } + + ~AutoHookIter() + { + if (m_pList) + m_pList->ReleaseIter(m_pIter); + } + + bool End() + { + return m_pIter->End(); + } + + void Next() + { + m_pIter->Next(); + } + + ISHDelegate *Handler() + { + return m_pIter->Handler(); + } + + int ThisPtrOffs() + { + return m_pIter->ThisPtrOffs(); + } + + void SetToZero() + { + m_pList = 0; + } + }; + + template struct DeprecatedCallClass + { + virtual B *GetThisPtr() = 0; + virtual void *GetOrigFunc(int vtbloffs, int vtblidx) = 0; + }; + + // 09.08.2008 (6 AM, I just woke up, the others are still sleeping so i finally can use this notebook !!) + // - Today is an important day. + // I'm adding support for functions which return references. + + // How it works: + // SH_SETUPCALLS doesn't use plain rettype to store the temporary return values (plugin ret, orig ret, + // override ret) anymore; instead, it uses SourceHook::ReferenceCarrier::type + // this is typedefed to the original rettype normally, but if the rettype is a reference, it's a special class + // which stores the reference as a pointer, and implements constructors, operator= and a conversion operator. + // special cases were needed for getoverrideret / getorigret; these are implemented through the + // SourceHook::MacroRefHelpers structs. + // Furthermore, SetOverrideRet had to be changed a bit; see SourceHook::OverrideFunctor somewhere down in this file. + template struct ReferenceCarrier + { + typedef T type; + }; + + template struct ReferenceCarrier + { + class type + { + T *m_StoredRef; + public: + type() : m_StoredRef(NULL) + { + } + type(T& ref) : m_StoredRef(&ref) + { + } + + T& operator= (T& ref) + { + m_StoredRef = &ref; + return ref; + } + + operator T& () const + { + return *m_StoredRef; + } + }; + }; + + /** + * @brief The main SourceHook interface + */ + class ISourceHook + { + public: + /** + * @brief Return interface version + */ + virtual int GetIfaceVersion() = 0; + + /** + * @brief Return implementation version + */ + virtual int GetImplVersion() = 0; + + /** + * @brief Add a hook. + * + * @return True if the function succeeded, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param iface The interface pointer + * @param ifacesize The size of the class iface points to + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + virtual bool AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, + ISHDelegate *handler, bool post) = 0; + + /** + * @brief Removes a hook. + * + * @return True if the function succeeded, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param iface The interface pointer + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + virtual bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, + ISHDelegate *handler, bool post) = 0; + + /** + * @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins + * + * @param plug The unique identifier of the plugin in question + */ + virtual bool IsPluginInUse(Plugin plug) = 0; + + /** + * @brief Return a pointer to a callclass. Generate a new one if required. + * + * @param iface The interface pointer + * @param size Size of the class instance + */ + virtual DeprecatedCallClass *GetCallClass(void *iface, size_t size) = 0; + + /** + * @brief Release a callclass + * + * @param ptr Pointer to the callclass + */ + virtual void ReleaseCallClass(DeprecatedCallClass *ptr) = 0; + + virtual void SetRes(META_RES res) = 0; //!< Sets the meta result + virtual META_RES GetPrevRes() = 0; //!< Gets the meta result of the + //!< previously calledhandler + virtual META_RES GetStatus() = 0; //!< Gets the highest meta result + virtual const void *GetOrigRet() = 0; //!< Gets the original result. + //!< If not in post function, undefined + virtual const void *GetOverrideRet() = 0; //!< Gets the override result. + //!< If none is specified, NULL + virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer + ////////////////////////////////////////////////////////////////////////// + // For hook managers + virtual void HookLoopBegin(IIface *pIface) = 0; //!< Should be called when a hook loop begins + virtual void HookLoopEnd() = 0; //!< Should be called when a hook loop exits + virtual void SetCurResPtr(META_RES *mres) = 0; //!< Sets pointer to the current meta result + virtual void SetPrevResPtr(META_RES *mres) = 0; //!< Sets pointer to previous meta result + virtual void SetStatusPtr(META_RES *mres) = 0; //!< Sets pointer to the status variable + virtual void SetIfacePtrPtr(void **pp) = 0; //!< Sets pointer to the interface this pointer + virtual void SetOrigRetPtr(const void *ptr) = 0; //!< Sets the original return pointer + virtual void SetOverrideRetPtr(void *ptr) = 0; //!< Sets the override result pointer + virtual bool ShouldContinue() = 0; //!< Returns false if the hook loop should exit + + /** + * @brief Remove a hook manager. Auto-removes all hooks attached to it from plugin plug. + * + * @param plug The owner of the hook manager + * @param pubFunc The hook manager's info function + */ + virtual void RemoveHookManager(Plugin plug, HookManagerPubFunc pubFunc) = 0; + + virtual void DoRecall() = 0; //!< Initiates a recall sequence + /* + HOW RECALLS WORK: + + The problem: + Users want the ability to change parameters of the called function + from inside their handler. + The solution: + 1) Mark as "recall" + 2) Recall the function + 3) => SH's hook func gets called: + 4) The first iterator points at the first hook the last hookfunc didn't execute yet + 5) does all iteration and returns normally + 6) The user's handler returns immediately + 7) The hook func returns immediately as well + + Also note that the recalled hookfunc starts with the status the recalling hookfunc + ended with. The last handler (doing the recall) is also able to specify its own + META_RES. + */ + + virtual void *GetOverrideRetPtr() = 0; //!< Returns the pointer set by SetOverrideRetPtr + + /** + * @brief Set up the hook loop. Equivalent to calling: + * SetStatusPtr, SetPrevResPtr, SetCurResPtr, SetIfacePtrPtr, SetOrigRetPtr, Get/SetOverrideRetPtr + * + * @param statusPtr pointer to status variable + * @param prevResPtr pointer to previous result variable + * @param curResPtr pointer to current result variable + * @param ifacePtrPtr pointer to interface this pointer variable + * @param origRetPr pointer to original return value variable. NULL for void funcs + * @param overrideRetPtr pointer to override return value variable. NULL for void funcs + * + * @return Override Return Pointer the hookfunc should use (may differ from overrideRetPtr + * when the hook func is being called as part of a recall + */ + virtual void *SetupHookLoop(META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr, + void **ifacePtrPtr, const void *origRetPtr, void *overrideRetPtr) = 0; + + /** + * @brief Modes for the new AddHook + */ + enum AddHookMode + { + Hook_Normal, + Hook_VP, + Hook_DVP + }; + + /** + * @brief Add a (VP) hook. + * + * @return non-zero hook id on success, 0 otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param mode Can be either Hook_Normal or Hook_VP (vtable-wide hook) + * @param iface The interface pointer + * @param ifacesize The size of the class iface points to + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + virtual int AddHookNew(Plugin plug, AddHookMode mode, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, + ISHDelegate *handler, bool post) = 0; + + /** + * @brief Remove a VP hook by ID. + * + * @return true on success, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param hookid The hook id (returned by AddHookNew) + */ + virtual bool RemoveHookByID(Plugin plug, int hookid) = 0; + + /** + * @brief Makes sure that hooks are going to be ignored on the next call of vfnptr + * + * @param plug The unique identifier of the plugin that calls this function + * @param vfnptr The virtual function pointer of the function in question + */ + virtual void SetIgnoreHooks(Plugin plug, void *vfnptr) = 0; + + /** + * @brief Reverses SetIgnoreHooks' effect + * + * @param plug The unique identifier of the plugin that calls this function + * @param vfnptr The virtual function pointer of the function in question + */ + virtual void ResetIgnoreHooks(Plugin plug, void *vfnptr) = 0; + + /** + * @brief Finds the original entry of a virtual function pointer + * + * @param vfnptr The virtual function pointer + * @return The original entry if the virtual function pointer has been patched; NULL otherwise. + */ + virtual void *GetOrigVfnPtrEntry(void *vfnptr) = 0; + }; + + // For META_RESULT_ORIG_RET and META_RESULT_OVERRIDE_RET: + // These have to be able to return references. If T is a reference, the pointers returned + // from the SH_GLOB_SHPTR are pointers to instances of ReferenceCarrier::type. + template struct MacroRefHelpers + { + inline static const T* GetOrigRet(ISourceHook *shptr) + { + return reinterpret_cast(shptr->GetOrigRet()); + } + inline static const T* GetOverrideRet(ISourceHook *shptr) + { + return reinterpret_cast(shptr->GetOverrideRet()); + } + }; + + template struct MacroRefHelpers + { + inline static T* GetOrigRet(ISourceHook *shptr) + { + T &ref = *reinterpret_cast::type *>(shptr->GetOrigRet()); + return &ref; + } + inline static T* GetOverrideRet(ISourceHook *shptr) + { + T &ref = *reinterpret_cast::type *>(shptr->GetOverrideRet()); + return &ref; + } + }; + + // For source-level compatibility + template struct CallClass + { + T *ptr; + + CallClass(T *p) : ptr(p) + { + } + + operator T*() + { + return ptr; + } + }; + + typedef CallClass GenericCallClass; + typedef CallClass ManualCallClass; + + template + CallClass *GetCallClass(T *p) + { + return new CallClass(p); + } + + template + void ReleaseCallClass(CallClass *p) + { + delete p; + } + + template + void *GetOrigVfnPtrEntry(X *pInstance, MFP mfp, ISourceHook *pSH) + { + SourceHook::MemFuncInfo info = {true, -1, 0, 0}; + SourceHook::GetFuncInfo(pInstance, mfp, info); + + void *vfnptr = reinterpret_cast( + *reinterpret_cast(reinterpret_cast(pInstance) + info.thisptroffs + info.vtbloffs) + info.vtblindex); + + void *origentry = pSH->GetOrigVfnPtrEntry(vfnptr); + + return origentry ? origentry : *reinterpret_cast(vfnptr); + } +} + +/************************************************************************/ +/* High level interface */ +/************************************************************************/ +#define META_RESULT_STATUS SH_GLOB_SHPTR->GetStatus() +#define META_RESULT_PREVIOUS SH_GLOB_SHPTR->GetPrevRes() +#define META_RESULT_ORIG_RET(type) *SourceHook::MacroRefHelpers::GetOrigRet(SH_GLOB_SHPTR) +#define META_RESULT_OVERRIDE_RET(type) *SourceHook::MacroRefHelpers::GetOverrideRet(SH_GLOB_SHPTR) +#define META_IFACEPTR(type) reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()) + +#define SET_META_RESULT(result) SH_GLOB_SHPTR->SetRes(result) +#define RETURN_META(result) do { SET_META_RESULT(result); return; } while(0) +#define RETURN_META_VALUE(result, value) do { SET_META_RESULT(result); return (value); } while(0) + +// If a hook on a function which returns a reference does not want to specify a return value, +// it can use this macro. +// ONLY USE THIS WITH MRES_IGNORED AND MRES_HANDLED !!! +#define RETURN_META_NOREF(result, rettype) do { SET_META_RESULT(result); return reinterpret_cast(*SH_GLOB_SHPTR); } while(0) + +// only call these from the hook handlers directly! +// :TODO: enforce it ? + +// Why take a memfuncptr instead of iface and func when we have to deduce the iface anyway now? +// Well, without it, there'd be no way to specify which overloaded version we want in _VALUE + +// SourceHook::SetOverrideRet is defined later. +#define RETURN_META_NEWPARAMS(result, memfuncptr, newparams) \ + do { \ + SET_META_RESULT(result); \ + SH_GLOB_SHPTR->DoRecall(); \ + (SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams; \ + RETURN_META(MRES_SUPERCEDE); \ + } while (0) + +#define RETURN_META_VALUE_NEWPARAMS(result, value, memfuncptr, newparams) \ + do { \ + SET_META_RESULT(result); \ + SH_GLOB_SHPTR->DoRecall(); \ + if ((result) >= MRES_OVERRIDE) \ + { \ + /* meh, set the override result here because we don't get a chance to return */ \ + /* before continuing the hook loop through the recall */ \ + SourceHook::SetOverrideResult(memfuncptr)(SH_GLOB_SHPTR, value); \ + } \ + RETURN_META_VALUE(MRES_SUPERCEDE, \ + (SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams); \ + } while (0) + +// :TODO: thisptroffs in MNEWPARAMS ?? + +#if SH_COMP == SH_COMP_MSVC + +#define SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname) \ + union \ + { \ + SH_MFHCls(hookname)::ECMFP mfp; \ + void *addr; \ + } u; \ + SourceHook::EmptyClass *thisptr = reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()); \ + u.addr = (*reinterpret_cast(reinterpret_cast(thisptr) + SH_MFHCls(hookname)::ms_MFI.vtbloffs))[ \ + SH_MFHCls(hookname)::ms_MFI.vtblindex]; + +#elif SH_COMP == SH_COMP_GCC + +#define SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname) \ + union \ + { \ + SH_MFHCls(hookname)::ECMFP mfp; \ + struct \ + { \ + void *addr; \ + intptr_t adjustor; \ + } s; \ + } u; \ + SourceHook::EmptyClass *thisptr = reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()); \ + u.s.addr = (*reinterpret_cast(reinterpret_cast(thisptr) + SH_MFHCls(hookname)::ms_MFI.vtbloffs))[ \ + SH_MFHCls(hookname)::ms_MFI.vtblindex]; \ + u.s.adjustor = 0; + +#endif + +#define RETURN_META_MNEWPARAMS(result, hookname, newparams) \ + do { \ + SET_META_RESULT(result); \ + SH_GLOB_SHPTR->DoRecall(); \ + SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname); \ + (thisptr->*(u.mfp)) newparams; \ + RETURN_META(MRES_SUPERCEDE); \ + } while (0) + +#define RETURN_META_VALUE_MNEWPARAMS(result, value, hookname, newparams) \ + do { \ + SET_META_RESULT(result); \ + SH_GLOB_SHPTR->DoRecall(); \ + if ((result) >= MRES_OVERRIDE) \ + { \ + /* see RETURN_META_VALUE_NEWPARAMS */ \ + SourceHook::SetOverrideResult(SH_GLOB_SHPTR, value); \ + } \ + SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname); \ + RETURN_META_VALUE(MRES_SUPERCEDE, (thisptr->*(u.mfp)) newparams); \ + } while (0) + +#define SH_MANUALHOOK_RECONFIGURE(hookname, pvtblindex, pvtbloffs, pthisptroffs) \ + do { \ + SH_GLOB_SHPTR->RemoveHookManager(SH_GLOB_PLUGPTR, SH_MFHCls(hookname)::HookManPubFunc); \ + SH_MFHCls(hookname)::ms_MFI.thisptroffs = pthisptroffs; \ + SH_MFHCls(hookname)::ms_MFI.vtblindex = pvtblindex; \ + SH_MFHCls(hookname)::ms_MFI.vtbloffs = pvtbloffs; \ + } while (0) + + +#define SH_GET_ORIG_VFNPTR_ENTRY(inst, mfp) (SourceHook::GetOrigVfnPtrEntry(inst, mfp, SH_GLOB_SHPTR)) + +// For source-level compatibility + +#define SH_GET_CALLCLASS(ptr) SourceHook::GetCallClass(ptr) +#define SH_GET_MCALLCLASS(ptr, size) SourceHook::GetCallClass(reinterpret_cast(ptr)) +#define SH_RELEASE_CALLCLASS(ptr) SourceHook::ReleaseCallClass(ptr) + +// New ADD / REMOVE macros. +#define SH_STATIC(func) fastdelegate::MakeDelegate(func) +#define SH_MEMBER(inst, func) fastdelegate::MakeDelegate(inst, func) + +#define SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ + __SourceHook_FHAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ + post, handler) + +#define SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ + __SourceHook_FHRemove##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ + post, handler) + +#define SH_ADD_MANUALHOOK(hookname, ifaceptr, handler, post) \ + __SourceHook_FHMAdd##hookname(reinterpret_cast(ifaceptr), post, handler) + +#define SH_REMOVE_MANUALHOOK(hookname, ifaceptr, handler, post) \ + __SourceHook_FHMRemove##hookname(reinterpret_cast(ifaceptr), post, handler) + +#define SH_ADD_VPHOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ + __SourceHook_FHVPAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ + post, handler, false) + +#define SH_ADD_DVPHOOK(ifacetype, ifacefunc, vtableptr, handler, post) \ + __SourceHook_FHVPAdd##ifacetype##ifacefunc(reinterpret_cast(vtableptr), \ + post, handler, true) + +#define SH_ADD_MANUALVPHOOK(hookname, ifaceptr, handler, post) \ + __SourceHook_FHMVPAdd##hookname(reinterpret_cast(ifaceptr), post, handler, false) + +#define SH_ADD_MANUALDVPHOOK(hookname, vtableptr, handler, post) \ + __SourceHook_FHMVPAdd##hookname(reinterpret_cast(vtableptr), post, handler, true) + +#define SH_REMOVE_HOOK_ID(hookid) \ + (SH_GLOB_SHPTR->RemoveHookByID(SH_GLOB_PLUGPTR, hookid)) + +// Old macros +// !! These are now deprecated. Instead, use one of these: +// SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) +// SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(inst, func), post) + +#define SH_ADD_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \ + SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) +#define SH_ADD_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \ + SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) + +// SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) +// SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(inst, func), post) + +#define SH_REMOVE_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \ + SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) +#define SH_REMOVE_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \ + SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) + +// SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) +// SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(inst, func), post) + +#define SH_ADD_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \ + SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) +#define SH_ADD_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \ + SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) + +// SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) +// SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(inst, func), post) + +#define SH_REMOVE_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \ + SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) +#define SH_REMOVE_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \ + SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) + +#define SH_NOATTRIB + + + + +#if SH_COMP == SH_COMP_MSVC +# define SH_SETUP_MFP(mfp) \ + reinterpret_cast(&mfp)[0] = vfnptr_origentry; +#elif SH_COMP == SH_COMP_GCC +# define SH_SETUP_MFP(mfp) \ + reinterpret_cast(&mfp)[0] = vfnptr_origentry; \ + reinterpret_cast(&mfp)[1] = 0; +#else +# error Not supported yet. +#endif + +////////////////////////////////////////////////////////////////////////// +#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov +#define SH_MFHCls(hookname) __SourceHook_MFHCls_##hookname + +#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \ + SH_FHCls(ifacetype,ifacefunc,overload)() \ + { \ + GetFuncInfo(funcptr, ms_MFI); \ + } \ + \ + static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::IHookManagerInfo *param) \ + { \ + using namespace ::SourceHook; \ + GetFuncInfo(funcptr, ms_MFI); \ + /* Verify interface version */ \ + if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \ + return 1; \ + if (SH_GLOB_SHPTR->GetImplVersion() < SH_IMPL_VERSION) \ + return 1; \ + \ + if (action == HA_GetInfo) \ + { \ + param->SetVersion(SH_HOOKMAN_VERSION); \ + param->SetInfo(ms_MFI.vtbloffs, ms_MFI.vtblindex, \ + reinterpret_cast(&ms_Proto)); \ + \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \ + param->SetHookfuncVfnptr( \ + reinterpret_cast(reinterpret_cast(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]); \ + return 0; \ + } \ + else if (action == HA_Register) \ + { \ + ms_HI = param; \ + return 0; \ + } \ + else if (action == HA_Unregister) \ + { \ + ms_HI = NULL; \ + return 0; \ + } \ + else \ + return 1; \ + } + +// It has to be possible to use the macros in namespaces +// -> So we need to access and extend the global SourceHook namespace +// We use a namespace alias for this +#define SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, funcptr) \ + struct SH_FHCls(ifacetype,ifacefunc,overload) \ + { \ + static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \ + static ::SourceHook::MemFuncInfo ms_MFI; \ + static ::SourceHook::IHookManagerInfo *ms_HI; \ + static ::SourceHook::ProtoInfo ms_Proto; \ + SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) + +#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, funcptr) \ + }; \ + SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \ + ::SourceHook::MemFuncInfo SH_FHCls(ifacetype,ifacefunc,overload)::ms_MFI; \ + ::SourceHook::IHookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \ + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \ + SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ + { \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0 || !mfi.isVirtual) \ + return false; /* No non-virtual functions / virtual inheritance supported */ \ + \ + return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, ::SourceHook::ISourceHook::Hook_Normal, iface, mfi.thisptroffs, \ + SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, \ + new CSHDelegate(handler), post); \ + } \ + int __SourceHook_FHVPAdd##ifacetype##ifacefunc(void *iface, bool post, \ + SH_FHCls(ifacetype,ifacefunc,overload)::FD handler, bool direct) \ + { \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0 || !mfi.isVirtual) \ + return false; /* No non-virtual functions / virtual inheritance supported */ \ + \ + return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, \ + direct ? ::SourceHook::ISourceHook::Hook_DVP : ::SourceHook::ISourceHook::Hook_VP, \ + iface, mfi.thisptroffs, SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, \ + new CSHDelegate(handler), post); \ + } \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ + { \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0) \ + return false; /* No virtual inheritance supported */ \ + \ + CSHDelegate tmp(handler); \ + return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, mfi.thisptroffs, \ + SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, &tmp, post); \ + } \ + +#define SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, pvtbloffs, pvtblidx, pthisptroffs) \ + struct SH_MFHCls(hookname) \ + { \ + static SH_MFHCls(hookname) ms_Inst; \ + static ::SourceHook::MemFuncInfo ms_MFI; \ + static ::SourceHook::IHookManagerInfo *ms_HI; \ + static ::SourceHook::ProtoInfo ms_Proto; \ + \ + SH_MFHCls(hookname)() \ + { \ + ms_MFI.isVirtual = true; \ + ms_MFI.thisptroffs = pthisptroffs; \ + ms_MFI.vtblindex = pvtblidx; \ + ms_MFI.vtbloffs = pvtbloffs; \ + } \ + static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::IHookManagerInfo *param) \ + { \ + using namespace ::SourceHook; \ + /* we don't set ms_MFI here because manual hookmans can be reconfigured */ \ + /* :FIXME: possible problem: someone adding a hook from a constructor of a global entity */ \ + /* which is construced before SH_MFHCls(hookname)() gets called? */ \ + /* Verify interface version */ \ + if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \ + return 1; \ + if (SH_GLOB_SHPTR->GetImplVersion() < SH_IMPL_VERSION) \ + return 1; \ + \ + if (action == HA_GetInfo) \ + { \ + param->SetVersion(SH_HOOKMAN_VERSION); \ + param->SetInfo(ms_MFI.vtbloffs, ms_MFI.vtblindex, \ + reinterpret_cast(&ms_Proto)); \ + \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(&SH_MFHCls(hookname)::Func, mfi); \ + param->SetHookfuncVfnptr( \ + reinterpret_cast(reinterpret_cast(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]); \ + return 0; \ + } \ + else if (action == HA_Register) \ + { \ + ms_HI = param; \ + return 0; \ + } \ + else if (action == HA_Unregister) \ + { \ + ms_HI = NULL; \ + return 0; \ + } \ + else \ + return 1; \ + } + +#define SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, pvtbloffs, pvtblidx, pthisptroffs) \ + }; \ + SH_MFHCls(hookname) SH_MFHCls(hookname)::ms_Inst; \ + ::SourceHook::MemFuncInfo SH_MFHCls(hookname)::ms_MFI; \ + ::SourceHook::IHookManagerInfo *SH_MFHCls(hookname)::ms_HI; \ + int __SourceHook_FHMAdd##hookname(void *iface, bool post, \ + SH_MFHCls(hookname)::FD handler) \ + { \ + return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, ::SourceHook::ISourceHook::Hook_Normal, iface, pthisptroffs, \ + SH_MFHCls(hookname)::HookManPubFunc, \ + new ::SourceHook::CSHDelegate(handler), post); \ + } \ + int __SourceHook_FHMVPAdd##hookname(void *iface, bool post, \ + SH_MFHCls(hookname)::FD handler, bool direct) \ + { \ + return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, \ + direct ? ::SourceHook::ISourceHook::Hook_DVP : ::SourceHook::ISourceHook::Hook_VP, \ + iface, pthisptroffs, SH_MFHCls(hookname)::HookManPubFunc, \ + new ::SourceHook::CSHDelegate(handler), post); \ + } \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + SH_MFHCls(hookname)::FD handler) \ + { \ + ::SourceHook::CSHDelegate tmp(handler); \ + return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, pthisptroffs, \ + SH_MFHCls(hookname)::HookManPubFunc, &tmp, post); \ + } \ + + +#define SH_SETUPCALLS(rettype, paramtypes, params) \ + /* 1) Find the vfnptr */ \ + using namespace ::SourceHook; \ + void *ourvfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \ + IVfnPtr *vfnptr = ms_HI->FindVfnPtr(ourvfnptr); \ + SH_ASSERT(vfnptr, ("Called with vfnptr 0x%p which couldn't be found in the list", ourvfnptr)); \ + \ + void *vfnptr_origentry = vfnptr->GetOrigEntry(); \ + /* ... and the iface */ \ + IIface *ifinfo = vfnptr->FindIface(reinterpret_cast(this)); \ + if (!ifinfo) \ + { \ + /* The iface info was not found. Redirect the call to the original function. */ \ + rettype (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + return (reinterpret_cast(this)->*mfp)params; \ + } \ + /* 2) Declare some vars and set it up */ \ + SH_GLOB_SHPTR->HookLoopBegin(ifinfo); \ + IHookList *prelist = ifinfo->GetPreHooks(); \ + IHookList *postlist = ifinfo->GetPostHooks(); \ + META_RES status = MRES_IGNORED; \ + META_RES prev_res; \ + META_RES cur_res; \ + typedef ReferenceCarrier::type my_rettype; \ + my_rettype orig_ret; \ + my_rettype override_ret; \ + my_rettype plugin_ret; \ + void* ifptr; \ + my_rettype *pOverrideRet = reinterpret_cast(SH_GLOB_SHPTR->SetupHookLoop( \ + &status, &prev_res, &cur_res, &ifptr, &orig_ret, &override_ret)); + +#define SH_CALL_HOOKS(post, params) \ + if (SH_GLOB_SHPTR->ShouldContinue()) \ + { \ + prev_res = MRES_IGNORED; \ + for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \ + { \ + cur_res = MRES_IGNORED; \ + ifptr = reinterpret_cast(reinterpret_cast(this) - iter.ThisPtrOffs()); \ + plugin_ret = reinterpret_cast*>(iter.Handler())->GetDeleg() params; \ + prev_res = cur_res; \ + if (cur_res > status) \ + status = cur_res; \ + if (cur_res >= MRES_OVERRIDE) \ + *pOverrideRet = plugin_ret; \ + if (!SH_GLOB_SHPTR->ShouldContinue()) \ + { \ + iter.SetToZero(); \ + break; \ + } \ + } \ + } + +#define SH_CALL_ORIG(rettype, paramtypes, params) \ + if (status != MRES_SUPERCEDE) \ + { \ + rettype (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + orig_ret = (reinterpret_cast(this)->*mfp)params; \ + } \ + else \ + orig_ret = override_ret; \ + +#define SH_RETURN() \ + SH_GLOB_SHPTR->HookLoopEnd(); \ + return status >= MRES_OVERRIDE ? *pOverrideRet : orig_ret; + +#define SH_HANDLEFUNC(paramtypes, params, rettype) \ + SH_SETUPCALLS(rettype, paramtypes, params) \ + SH_CALL_HOOKS(pre, params) \ + SH_CALL_ORIG(rettype, paramtypes, params) \ + SH_CALL_HOOKS(post, params) \ + SH_RETURN() + +////////////////////////////////////////////////////////////////////////// +#define SH_SETUPCALLS_void(paramtypes, params) \ + /* 1) Find the vfnptr */ \ + using namespace ::SourceHook; \ + void *ourvfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \ + IVfnPtr *vfnptr = ms_HI->FindVfnPtr(ourvfnptr); \ + SH_ASSERT(vfnptr, ("Called with vfnptr 0x%p which couldn't be found in the list", ourvfnptr)); \ + \ + void *vfnptr_origentry = vfnptr->GetOrigEntry(); \ + /* ... and the iface */ \ + IIface *ifinfo = vfnptr->FindIface(reinterpret_cast(this)); \ + if (!ifinfo) \ + { \ + /* The iface info was not found. Redirect the call to the original function. */ \ + void (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + (reinterpret_cast(this)->*mfp)params; \ + return; \ + } \ + /* 2) Declare some vars and set it up */ \ + SH_GLOB_SHPTR->HookLoopBegin(ifinfo); \ + IHookList *prelist = ifinfo->GetPreHooks(); \ + IHookList *postlist = ifinfo->GetPostHooks(); \ + META_RES status = MRES_IGNORED; \ + META_RES prev_res; \ + META_RES cur_res; \ + void* ifptr; \ + SH_GLOB_SHPTR->SetupHookLoop(&status, &prev_res, &cur_res, &ifptr, NULL, NULL); \ + +#define SH_CALL_HOOKS_void(post, params) \ + if (SH_GLOB_SHPTR->ShouldContinue()) \ + { \ + prev_res = MRES_IGNORED; \ + for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \ + { \ + cur_res = MRES_IGNORED; \ + ifptr = reinterpret_cast(reinterpret_cast(this) - iter.ThisPtrOffs()); \ + reinterpret_cast*>(iter.Handler())->GetDeleg() params; \ + prev_res = cur_res; \ + if (cur_res > status) \ + status = cur_res; \ + if (!SH_GLOB_SHPTR->ShouldContinue()) \ + { \ + iter.SetToZero(); \ + break; \ + } \ + } \ + } + +#define SH_CALL_ORIG_void(paramtypes, params) \ + if (status != MRES_SUPERCEDE) \ + { \ + void (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + (reinterpret_cast(this)->*mfp)params; \ + } + +#define SH_RETURN_void() \ + SH_GLOB_SHPTR->HookLoopEnd(); + +#define SH_HANDLEFUNC_void(paramtypes, params) \ + SH_SETUPCALLS_void(paramtypes, params) \ + SH_CALL_HOOKS_void(pre, params) \ + SH_CALL_ORIG_void(paramtypes, params) \ + SH_CALL_HOOKS_void(post, params) \ + SH_RETURN_void() + + +// Special vafmt handlers +// :TODO: what +#define SH_HANDLEFUNC_vafmt(paramtypes, params_orig, params_plug, rettype) \ + SH_SETUPCALLS(rettype, paramtypes, params_orig) \ + SH_CALL_HOOKS(pre, params_plug) \ + SH_CALL_ORIG(rettype, paramtypes, params_orig) \ + SH_CALL_HOOKS(post, params_plug) \ + SH_RETURN() + +#define SH_HANDLEFUNC_void_vafmt(paramtypes, params_orig, params_plug) \ + SH_SETUPCALLS_void(paramtypes, params_orig) \ + SH_CALL_HOOKS_void(pre, params_plug) \ + SH_CALL_ORIG_void(paramtypes, params_orig) \ + SH_CALL_HOOKS_void(post, params_plug) \ + SH_RETURN_void() + +////////////////////////////////////////////////////////////////////////// + +// :FIXME: +// sizeof on references returns the size of the datatype, NOT the pointer size or something +// -> one should probably flag references in __SourceHook_ParamSizes_* ! +// or simply assume that their size is sizeof(void*)=SH_PTRSIZE... could be doable through a simple template + + +// ********* Support for 0 arguments ********* +#define SH_DECL_HOOK0(ifacetype, ifacefunc, attr, overload, rettype) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate0 FD; \ + virtual rettype Func() \ + { SH_HANDLEFUNC((), (), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0 }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 0, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK0_void(ifacetype, ifacefunc, attr, overload) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate0<> FD; \ + virtual void Func() \ + { SH_HANDLEFUNC_void((), ()); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0 }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 0, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK0_vafmt(ifacetype, ifacefunc, attr, overload, rettype) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate1 FD; \ + virtual rettype Func(const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((...), ("%s", buf), (buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1 }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 0, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK0_void_vafmt(ifacetype, ifacefunc, attr, overload) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate1 FD; \ + virtual void Func(const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((...), ("%s", buf), (buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1 }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 0, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK0(hookname, vtblidx, vtbloffs, thisptroffs, rettype) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate0 FD; \ + virtual rettype Func() \ + { SH_HANDLEFUNC((), (), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0 }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 0, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK0_void(hookname, vtblidx, vtbloffs, thisptroffs) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate0<> FD; \ + virtual void Func() \ + { SH_HANDLEFUNC_void((), ()); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0 }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 0, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 1 arguments ********* +#define SH_DECL_HOOK1(ifacetype, ifacefunc, attr, overload, rettype, param1) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate1 FD; \ + virtual rettype Func(param1 p1) \ + { SH_HANDLEFUNC((param1), (p1), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 1, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK1_void(ifacetype, ifacefunc, attr, overload, param1) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate1 FD; \ + virtual void Func(param1 p1) \ + { SH_HANDLEFUNC_void((param1), (p1)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 1, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK1_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate2 FD; \ + virtual rettype Func(param1 p1, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, ...), (p1, "%s", buf), (p1, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 1, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK1_void_vafmt(ifacetype, ifacefunc, attr, overload, param1) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate2 FD; \ + virtual void Func(param1 p1, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, ...), (p1, "%s", buf), (p1, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 1, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK1(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate1 FD; \ + virtual rettype Func(param1 p1) \ + { SH_HANDLEFUNC((param1), (p1), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 1, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK1_void(hookname, vtblidx, vtbloffs, thisptroffs, param1) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate1 FD; \ + virtual void Func(param1 p1) \ + { SH_HANDLEFUNC_void((param1), (p1)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 1, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 2 arguments ********* +#define SH_DECL_HOOK2(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate2 FD; \ + virtual rettype Func(param1 p1, param2 p2) \ + { SH_HANDLEFUNC((param1, param2), (p1, p2), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 2, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK2_void(ifacetype, ifacefunc, attr, overload, param1, param2) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate2 FD; \ + virtual void Func(param1 p1, param2 p2) \ + { SH_HANDLEFUNC_void((param1, param2), (p1, p2)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 2, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK2_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate3 FD; \ + virtual rettype Func(param1 p1, param2 p2, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, ...), (p1, p2, "%s", buf), (p1, p2, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 2, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK2_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate3 FD; \ + virtual void Func(param1 p1, param2 p2, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, ...), (p1, p2, "%s", buf), (p1, p2, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 2, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK2(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate2 FD; \ + virtual rettype Func(param1 p1, param2 p2) \ + { SH_HANDLEFUNC((param1, param2), (p1, p2), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 2, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK2_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate2 FD; \ + virtual void Func(param1 p1, param2 p2) \ + { SH_HANDLEFUNC_void((param1, param2), (p1, p2)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 2, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 3 arguments ********* +#define SH_DECL_HOOK3(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate3 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3) \ + { SH_HANDLEFUNC((param1, param2, param3), (p1, p2, p3), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 3, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK3_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate3 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3) \ + { SH_HANDLEFUNC_void((param1, param2, param3), (p1, p2, p3)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 3, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK3_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate4 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, ...), (p1, p2, p3, "%s", buf), (p1, p2, p3, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 3, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK3_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate4 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, ...), (p1, p2, p3, "%s", buf), (p1, p2, p3, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 3, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK3(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate3 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3) \ + { SH_HANDLEFUNC((param1, param2, param3), (p1, p2, p3), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 3, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK3_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate3 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3) \ + { SH_HANDLEFUNC_void((param1, param2, param3), (p1, p2, p3)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 3, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 4 arguments ********* +#define SH_DECL_HOOK4(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate4 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4) \ + { SH_HANDLEFUNC((param1, param2, param3, param4), (p1, p2, p3, p4), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 4, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK4_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate4 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4), (p1, p2, p3, p4)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 4, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK4_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate5 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, ...), (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 4, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK4_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate5 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, ...), (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 4, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK4(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate4 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4) \ + { SH_HANDLEFUNC((param1, param2, param3, param4), (p1, p2, p3, p4), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 4, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK4_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate4 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4), (p1, p2, p3, p4)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 4, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 5 arguments ********* +#define SH_DECL_HOOK5(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate5 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 5, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK5_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate5 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 5, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK5_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate6 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, ...), (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 5, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK5_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate6 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, ...), (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 5, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK5(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate5 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 5, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK5_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate5 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 5, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 6 arguments ********* +#define SH_DECL_HOOK6(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate6 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 6, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK6_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate6 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 6, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK6_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate7 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, ...), (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 6, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK6_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate7 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, ...), (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 6, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK6(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate6 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 6, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK6_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate6 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 6, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 7 arguments ********* +#define SH_DECL_HOOK7(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate7 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 7, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK7_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate7 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 7, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK7_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate8 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, ...), (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 7, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK7_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate8 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, ...), (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 7, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK7(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate7 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 7, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK7_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate7 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 7, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 8 arguments ********* +#define SH_DECL_HOOK8(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate8 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 8, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK8_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate8 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 8, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK8_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate9 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, ...), (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 8, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK8_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate9 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, ...), (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 8, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK8(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate8 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 8, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK8_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate8 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 8, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 9 arguments ********* +#define SH_DECL_HOOK9(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate9 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 9, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK9_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate9 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 9, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK9_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate10 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 9, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK9_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate10 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 9, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK9(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate9 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 9, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK9_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate9 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 9, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 10 arguments ********* +#define SH_DECL_HOOK10(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate10 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 10, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK10_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate10 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 10, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK10_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate11 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 10, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK10_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate11 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 10, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK10(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate10 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 10, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK10_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate10 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 10, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 11 arguments ********* +#define SH_DECL_HOOK11(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate11 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 11, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK11_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate11 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 11, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK11_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate12 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 11, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK11_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate12 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 11, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK11(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate11 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 11, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK11_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate11 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 11, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 12 arguments ********* +#define SH_DECL_HOOK12(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate12 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 12, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK12_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate12 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 12, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK12_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate13 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 12, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK12_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate13 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 12, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK12(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate12 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 12, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK12_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate12 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 12, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 13 arguments ********* +#define SH_DECL_HOOK13(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate13 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 13, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK13_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate13 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 13, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK13_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate14 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 13, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK13_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate14 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 13, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK13(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate13 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 13, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK13_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate13 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 13, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 14 arguments ********* +#define SH_DECL_HOOK14(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate14 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 14, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK14_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate14 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 14, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK14_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate15 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 14, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK14_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate15 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 14, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK14(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate14 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 14, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK14_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate14 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 14, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 15 arguments ********* +#define SH_DECL_HOOK15(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate15 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 15, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK15_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate15 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 15, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK15_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate16 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 15, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK15_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate16 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 15, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK15(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate15 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 15, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK15_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate15 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 15, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 16 arguments ********* +#define SH_DECL_HOOK16(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate16 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 16, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK16_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate16 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 16, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK16_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate17 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 16, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK16_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate17 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 16, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK16(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate16 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 16, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK16_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate16 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 16, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 17 arguments ********* +#define SH_DECL_HOOK17(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate17 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 17, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK17_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate17 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 17, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK17_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate18 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 17, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK17_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate18 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 17, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK17(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate17 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 17, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK17_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate17 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 17, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 18 arguments ********* +#define SH_DECL_HOOK18(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate18 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 18, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK18_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate18 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 18, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK18_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate19 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 18, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK18_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate19 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 18, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK18(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate18 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 18, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK18_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate18 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 18, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 19 arguments ********* +#define SH_DECL_HOOK19(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate19 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 19, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK19_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate19 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 19, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK19_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate20 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 19, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK19_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate20 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 19, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK19(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate19 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 19, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK19_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate19 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 19, __SourceHook_ParamSizesM_##hookname); \ + + +// ********* Support for 20 arguments ********* +#define SH_DECL_HOOK20(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate20 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19), sizeof(param20) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 20, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK20_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate20 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19), sizeof(param20) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 20, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK20_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate21 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, buf), rettype); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19), sizeof(param20) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \ + 20, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_HOOK20_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ + SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ + (&ifacetype::ifacefunc))) \ + typedef fastdelegate::FastDelegate21 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \ + { \ + char buf[::SourceHook::STRBUF_LEN]; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(buf, sizeof(buf), fmt, ap); \ + va_end(ap); \ + SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, buf)); \ + } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ + (static_cast(&ifacetype::ifacefunc))) \ + \ + const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19), sizeof(param20) }; \ + ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \ + 20, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload); + +#define SH_DECL_MANUALHOOK20(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate20 FD; \ + virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ + { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), rettype); } \ + typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20); \ + typedef rettype RetType; \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19), sizeof(param20) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \ + 20, __SourceHook_ParamSizesM_##hookname); \ + +#define SH_DECL_MANUALHOOK20_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ + SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + typedef fastdelegate::FastDelegate20 FD; \ + virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ + { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); } \ + typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20); \ + SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ + \ + const int __SourceHook_ParamSizesM_##hookname[] = { 0, sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6), sizeof(param7), sizeof(param8), sizeof(param9), sizeof(param10), sizeof(param11), sizeof(param12), sizeof(param13), sizeof(param14), sizeof(param15), sizeof(param16), sizeof(param17), sizeof(param18), sizeof(param19), sizeof(param20) }; \ + ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \ + 20, __SourceHook_ParamSizesM_##hookname); \ + + + + +////////////////////////////////////////////////////////////////////////// +// SH_CALL + +#define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \ +{ \ + using namespace ::SourceHook; \ + \ + m_pSH->SetIgnoreHooks(m_Plug, m_VfnPtr); \ + RetType tmpret = (m_ThisPtr->*m_MFP)call; \ + m_pSH->ResetIgnoreHooks(m_Plug, m_VfnPtr); \ + return tmpret; \ +} + +#define SH_MAKE_EXECUTABLECLASS_OB_void(call, prms) \ +{ \ + using namespace ::SourceHook; \ + \ + m_pSH->SetIgnoreHooks(m_Plug, m_VfnPtr); \ + (m_ThisPtr->*m_MFP)call; \ + m_pSH->ResetIgnoreHooks(m_Plug, m_VfnPtr); \ +} + +namespace SourceHook +{ + // Call Class Wrapper! + template struct CCW + { + typedef T type; + + // Get Real Pointer! + static inline T *GRP(T *p) + { + return p; + } + }; + + template struct CCW< CallClass > + { + typedef T type; + + // Get Real Pointer! + static inline T *GRP(CallClass *p) + { + return p->ptr; + } + }; + + + // Support for 0 arguments + template class ExecutableClass0 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass0(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()() const + SH_MAKE_EXECUTABLECLASS_OB((), ()) + + + template RetType operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB((p1), (Param1)) + + template RetType operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2), (Param1, Param2)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3), (Param1, Param2, Param3)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass0 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass0(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()() const + SH_MAKE_EXECUTABLECLASS_OB_void((), ()) + + + template void operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1), (Param1)) + + template void operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2), (Param1, Param2)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3), (Param1, Param2, Param3)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 1 arguments + template class ExecutableClass1 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass1(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB((p1), (Param1)) + + + template RetType operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2), (Param1, Param2)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3), (Param1, Param2, Param3)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass1 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass1(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1), (Param1)) + + + template void operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2), (Param1, Param2)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3), (Param1, Param2, Param3)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 2 arguments + template class ExecutableClass2 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass2(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2), (Param1, Param2)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3), (Param1, Param2, Param3)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass2 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass2(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2), (Param1, Param2)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3), (Param1, Param2, Param3)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 3 arguments + template class ExecutableClass3 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass3(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3), (Param1, Param2, Param3)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass3 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass3(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3), (Param1, Param2, Param3)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 4 arguments + template class ExecutableClass4 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass4(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass4 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass4(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 5 arguments + template class ExecutableClass5 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass5(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass5 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass5(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 6 arguments + template class ExecutableClass6 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass6(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass6 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass6(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 7 arguments + template class ExecutableClass7 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass7(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass7 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass7(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 8 arguments + template class ExecutableClass8 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass8(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass8 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass8(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 9 arguments + template class ExecutableClass9 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass9(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass9 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass9(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 10 arguments + template class ExecutableClass10 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass10(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass10 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass10(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 11 arguments + template class ExecutableClass11 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass11(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass11 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass11(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 12 arguments + template class ExecutableClass12 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass12(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass12 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass12(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 13 arguments + template class ExecutableClass13 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass13(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass13 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass13(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 14 arguments + template class ExecutableClass14 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass14(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass14 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass14(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 15 arguments + template class ExecutableClass15 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass15(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass15 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass15(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 16 arguments + template class ExecutableClass16 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass16(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass16 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass16(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 17 arguments + template class ExecutableClass17 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass17(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass17 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass17(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 18 arguments + template class ExecutableClass18 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass18(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass18 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass18(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 19 arguments + template class ExecutableClass19 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass19(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass19 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass19(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 20 arguments + template class ExecutableClass20 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass20(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + + }; + + template class ExecutableClass20 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFP m_MFP; + ISourceHook *m_pSH; + Plugin m_Plug; + public: + ExecutableClass20(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + + }; + + +} + +#define SH__CALL_GET_VFNPTR_NORMAL \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(CCW::GRP(ptr), mfp, mfi); \ + void *vfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(CCW::GRP(ptr)) + mfi.thisptroffs + mfi.vtbloffs) + mfi.vtblindex); + +#define SH__CALL_GET_VFNPTR_MANUAL \ + using namespace ::SourceHook; \ + void *vfnptr = reinterpret_cast( \ + *reinterpret_cast( (reinterpret_cast(CCW::GRP(ptr)) + thisptroffs + vtbloffs) ) + vtblidx); \ + /* patch mfp */ \ + *reinterpret_cast(&mfp) = *reinterpret_cast(vfnptr); + +// SH_CALL needs to deduce the return type -> it uses templates and function overloading +// That's why SH_CALL takes two parameters: "mfp2" of type RetType(X::*mfp)(params), and "mfp" of type MFP +// The only purpose of the mfp2 parameter is to extract the return type + + +// Support for 0 arguments +template +SourceHook::ExecutableClass0::type, MFP, RetType> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass0::type, MFP, RetType>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass0::type, MFP, RetType> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)()const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass0::type, MFP, RetType>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass0 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass0( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 1 arguments +template +SourceHook::ExecutableClass1::type, MFP, RetType, Param1> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass1::type, MFP, RetType, Param1>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass1::type, MFP, RetType, Param1> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass1::type, MFP, RetType, Param1>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass1 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass1( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 2 arguments +template +SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass2 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass2( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 3 arguments +template +SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass3 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass3( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 4 arguments +template +SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass4 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass4( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 5 arguments +template +SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass5 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass5( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 6 arguments +template +SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass6 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass6( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 7 arguments +template +SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass7 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass7( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 8 arguments +template +SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass8 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass8( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 9 arguments +template +SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass9 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass9( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 10 arguments +template +SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass10 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass10( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 11 arguments +template +SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass11 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass11( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 12 arguments +template +SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass12 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass12( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 13 arguments +template +SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass13 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass13( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 14 arguments +template +SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass14 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass14( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 15 arguments +template +SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass15 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass15( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 16 arguments +template +SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass16 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass16( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 17 arguments +template +SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass17 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass17( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 18 arguments +template +SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass18 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass18( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 19 arguments +template +SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass19 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass19( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + +// Support for 20 arguments +template +SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass20 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass20( + reinterpret_cast(CCW::GRP(ptr)), mfp, vfnptr, shptr, plug); +} + + +#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300 +// GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it + + +// Support for 0 arguments +template +SourceHook::ExecutableClass0::type, MFP, RetType> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass0::type, MFP, RetType>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass0::type, MFP, RetType> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass0::type, MFP, RetType>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 1 arguments +template +SourceHook::ExecutableClass1::type, MFP, RetType, Param1> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass1::type, MFP, RetType, Param1>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass1::type, MFP, RetType, Param1> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass1::type, MFP, RetType, Param1>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 2 arguments +template +SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass2::type, MFP, RetType, Param1, Param2>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 3 arguments +template +SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass3::type, MFP, RetType, Param1, Param2, Param3>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 4 arguments +template +SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass4::type, MFP, RetType, Param1, Param2, Param3, Param4>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 5 arguments +template +SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass5::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 6 arguments +template +SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass6::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 7 arguments +template +SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass7::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 8 arguments +template +SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass8::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 9 arguments +template +SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass9::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 10 arguments +template +SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass10::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 11 arguments +template +SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass11::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 12 arguments +template +SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass12::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 13 arguments +template +SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass13::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 14 arguments +template +SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass14::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 15 arguments +template +SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass15::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 16 arguments +template +SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass16::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 17 arguments +template +SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass17::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 18 arguments +template +SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass18::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 19 arguments +template +SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass19::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + +// Support for 20 arguments +template +SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + +template +SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20> +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass20::type, MFP, RetType, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20>(CCW::GRP(ptr), + mfp, vfnptr, shptr, plug); +} + + + +#endif + +#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp), SH_GLOB_SHPTR, SH_GLOB_PLUGPTR) +#define SH_MCALL2(ptr, mfp, vtblidx, vtbloffs, thisptroffs) SH_MCALL3((ptr), (mfp), (mfp), (vtblidx), (vtbloffs), (thisptroffs), SH_GLOB_SHPTR, SH_GLOB_PLUGPTR) +#define SH_MCALL(ptr, mhookname) SH_MCALL2((ptr), SH_MFHCls(mhookname)::ECMFP(), SH_MFHCls(mhookname)::ms_MFI.vtblindex, \ + SH_MFHCls(mhookname)::ms_MFI.vtbloffs, SH_MFHCls(mhookname)::ms_MFI.thisptroffs) + +#undef SH_MAKE_EXECUTABLECLASS_OB + +////////////////////////////////////////////////////////////////////////// +// SetOverrideRet and RecallGetIface for recalls +// These take a ISourceHook pointer instead of using SH_GLOB_SHPTR directly +// The reason is that the user may want to redefine SH_GLOB_SHPTR - then the macros +// (META_RETURN_VALUE_NEWPARAMS) should obey the new pointer. + +namespace SourceHook +{ + template + void SetOverrideResult(ISourceHook *shptr, const RetType res) + { + *reinterpret_cast(shptr->GetOverrideRetPtr()) = res; + } + + // SetOverrideResult used to be implemented like this: + // SetOverrideResult(shptr, memfuncptr, return); + // normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference + // (it thought it was ambigous - the ref and non-ref type) + // so now SetOverrideResult(memfuncptr) deduces the ret type, and returns a functor which does the work + // new syntax: SetOverrideResult(memfuncptr)(shptr, return) + // This also allows us to create a special version for references which respects ReferenceCarrier. + + template struct OverrideFunctor + { + void operator()(ISourceHook *shptr, T res) + { + *reinterpret_cast(shptr->GetOverrideRetPtr()) = res; + } + }; + template struct OverrideFunctor + { + void operator()(ISourceHook *shptr, T &res) + { + // overrideretptr points to ReferenceCarrier + *reinterpret_cast::type *>(shptr->GetOverrideRetPtr()) = res; + } + }; + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)()) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)()) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + +} + +#endif + // The pope is dead. -> :( diff --git a/utils/mmsource/core-legacy/sourcehook/sourcehook_impl.h b/utils/mmsource/core-legacy/sourcehook/sourcehook_impl.h new file mode 100644 index 00000000..ac1c5fd1 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/sourcehook_impl.h @@ -0,0 +1,817 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2007 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +#ifndef __SOURCEHOOK_IMPL_H__ +#define __SOURCEHOOK_IMPL_H__ + +#include "sourcehook.h" +#include "sh_list.h" +#include "sh_vector.h" +#include "sh_tinyhash.h" +#include "sh_stack.h" +#include "sh_listcat.h" + +/* + +IMPLEMENTATION INFO + +--------------------------------------- +Protos ("Prototypes") + The purpose of protos is to provide the amount of type information about a function + which is required to be able to execute a function call without corrupting the stack. + Our protos do not fully do this, but they provide the size of the return value, the number of + parameters, and the size of each parameter, which is enough for most situations. + + There are two version of protos: + OLD: + C-Style strings. + + 0_void: + "attrib" + 1_void: + "attrib|param1_type" + 2_void: + "attrib|param1_type|param2_type + 0: + "attrib|ret_type" + 1: + "attrib|ret_type|param1_type" + 2: + "attrib|ret_type|param2_type" + + Old protos are deprecated. + + NEW: + New protos are in fact pointers to the ProtoInfo structure (see sourcehook.h) + + Old protos begin with a non-zero byte, new protos begin with a zero byte. + + Protos are usually stored in a CProto instance. + +--------------------------------------- +Hook managers and hook manager containers + Each hookman container is tied to _one_ proto/vtable index/vtable offset info. + Hookman containers then contain a list of hook managers provided by plugins, sorted by version. + (higher versions come first) + + Duplicate hook managers are ignored (ie. hook managers where proto, vtable index, vtable offset, + plugin, version are the same as in an already exisiting hook manager) + + A new hook manager is always added to the end of the version group in the corresponding + hook container. + + If the new hook manager was added to the beginning of the container (which only happens if + it is the first one or if it has a higher version than the previously first hook manager), + the now second hook manager is shut down and the new hook manager takes its job. + + A "hook manager container id" (HMCI) consits of three values: proto, vtbl index, vtbl offset. +--------------------------------------- +Hooks + When adding a hook, first the proposed hook manager is added to the corresponding + hook manager container as described above. + + Then the first hook manager in the the manhook container is chosen to handle the function. + + Removing a hook does not neccessarily unreigster the plugin's hook manager. In order to do this, + use RemoveHookManager or UnloadPlugin/ + + Hooks can be paused - they remain in memory but they are not called. In SH, the hook iterator + classes handle pausing transparently. + + The hook loop is supposed to call ShouldContinue before each iteration. This makes hook handlers + able to remove themselves. + +--------------------------------------- +Call classes + + !! deprecated !! - see below (new SH_CALL) + + Call classes are identified by a this pointer and an instance size + + We use the instance size because a derived class instance and a base class instance could + have the same this pointers, and we want to avoid that the derived class + (which could be bigger) gets the same callclass as the base class (mainly if the + base class' callclass was requested first). + + Call classes are reference counted. + + The original function pointers are stored in a vector (in order to allow fast random access). + These vectors are stored as the value type of a hash. The key type is int and represents the + vtable offset. + + If the hash key doesn't exist or the vtblidx is out of range or the corresponding element in the + vector is NULL, there is no hook on that function. + +--------------------------------------- +Recalls + Recalls are used for the META_RETURN_(VALUE_)NEWPARAMS macros, ie. to change the parameters + in the hook loop on the fly. + + First, the macro calls DoRecall(), then it calls the function the hook is attached to -> it + calls the hookfunc. SourceHook makes sure that the newly invoked hook loop starts where the last + one left off and that status variables like status, previous result, override return are kept. + When this recurisvely called hookfunc returns, the macro returns what it returned + (using MRES_SUPERCEDE). CSourceHookImpl returns false from ShouldContinue so the original hook loop + is abandonned. + +Post Recalls + People wanted to be able to use META_RETURN_(VALUE_)NEWPARAMS from post hooks as well. Crazy people! + Anyway, for this, we have to know where a hook handler is. Is it executing pre or post hooks at the moment? + The only way we can know this is watching when it calls CHookList::GetIter(). So CHookList gets a new variable: + m_RequestedFlag. It also gets two new functions: RQFlagReset() and RQFlagGet(). + HookLoopBegin() calls RQFlagReset on both hooklists of the iface; then DoRecall() checks whether the postlist's + RQ flag is set. if yes, the hook loop is in post mode. + + So, what a about a recall in post mode? The first ShouldContinue returns false and sets Status to supercede. + This way the pre hooks and the function call will be skipped. Then, then next ShouldContinue returns true, so we get + into the post hooks. HA! + +Return Values in Post Recalls + The easy case is when we already have an override return value. In this case, the status register gets transferred, + and so does the override return pointer. So, basically, everything is ok. + + However, what happens if we don't? ie. the status register is on MRES_IGNORED? In this case we'd have to transfer the + orig ret value. But we can't: There's no way to tell the hookfunc: "Use this as orig ret pointer". It uses its own. + So, we emulate it. GetOrigRet will return the orig ret pointer from the old hook loop. If still no one overrides it, + we'd have to return it. BUT! HOW TO DO THIS? Check out SH_RETURN(). First calls HookLoopEnd(), then decides whether + to return the override retval or the orig retval. But it doesn't ask for a new override return. So we give the function + the last orig return value as its new override return value; but leave status where it is so everything works, and in + HookLoopEnd we make sure that status is high enough so that the override return will be returned. crazy. + + All this stuff could be much less complicated if I didn't try to preserve binary compatibility :) + +VP Hooks + VP hooks are hooks which are called on a vfnptr, regardless of the this pointer with which it was called. They are + implemented as a special CIface instance with m_Ptr = NULL. All Hook Lists have a new "ListCatIterator" which + virtually concatenates the NULL-interface-hook-list with their normal hook list. + + + I'm afraid that with the addition of Recalls and VP Hooks, SourceHook is now a pretty complex and hacked-together + binary compatible beast which is pretty hard to maintain unless you've written it :) + +New SH_CALL + The addition of VP hooks messed up the Call Classes concept (see above) - call classes are bound to an + instance pointer; they only work on one of the hooked instances. But VP hooks are called on all instances. + + That's why now, SH_CALL takes an instance pointer instead of a callclass pointer. It basically does this: + 1) call SH_GLOB_PTR->SetIgnoreHooks(vfnptr) + 2) call this->*mfp + 3) call SH_GLOB_PTR->ResetIgnoreHooks(vfnptr) + + SourceHook stroes the "ignored vfnptr" and makes CVfnPtr::FindIface return NULL if the CVfnPtr instance + corresponds to the ignored vfnptr. This way the hook manager thinks that the instance isn't hooked, and calls + the original function. Everything works fine. This works even for VP hooks. +*/ + +namespace SourceHook +{ + /** + * @brief The SourceHook implementation class + */ + class CSourceHookImpl : public ISourceHook + { + private: + class CProto + { + char *m_Proto; + + static bool Equal(const char *p1, const char *p2); + char *DupProto(const char *src); + void FreeProto(char *prot); + public: + CProto() : m_Proto(NULL) + { + } + + CProto(const char *szProto) : m_Proto(DupProto(szProto)) + { + } + + CProto(const CProto &other) : m_Proto(DupProto(other.m_Proto)) + { + } + + ~CProto() + { + FreeProto(m_Proto); + m_Proto = NULL; + } + + void operator = (const char *szProto) + { + m_Proto = DupProto(szProto); + } + + void operator = (const CProto &other) + { + m_Proto = DupProto(other.m_Proto); + } + + bool operator == (const char *szProto) const + { + return Equal(szProto, m_Proto); + } + bool operator == (const CProto &other) const + { + return Equal(other.m_Proto, m_Proto); + } + + const char *GetProto() const + { + return m_Proto; + } + }; + + + /** + * @brief A hook can be removed if you have this information + */ + struct RemoveHookInfo + { + RemoveHookInfo(Plugin pplug, void *piface, int tpo, HookManagerPubFunc phookman, + ISHDelegate *phandler, bool ppost) + : plug(pplug), iface(piface), thisptr_offs(tpo), + hookman(phookman), handler(phandler), post(ppost) + { + } + + Plugin plug; + void *iface; + int thisptr_offs; + HookManagerPubFunc hookman; + ISHDelegate *handler; + bool post; + }; + + struct RemoveHookManInfo + { + RemoveHookManInfo(Plugin pplug, HookManagerPubFunc phookman) + : plug(pplug), hookman(phookman) + { + } + + Plugin plug; + HookManagerPubFunc hookman; + }; + + // Associates hook ids with info about the hooks + // Also used to keep track of used hook ids + class CHookIDManager + { + public: + struct Entry + { + bool isfree; + + // hookman info + CProto proto; + int vtbl_offs; + int vtbl_idx; + + // vfnptr + void *vfnptr; + + // iface + void* adjustediface; + + // hook + Plugin plug; + int thisptr_offs; + ISHDelegate *handler; + bool post; + + Entry(const CProto &pprt, int pvo, int pvi, void *pvp, void *pai, Plugin pplug, int pto, + ISHDelegate *ph, bool ppost) + : isfree(false), proto(pprt), vtbl_offs(pvo), vtbl_idx(pvi), vfnptr(pvp), + adjustediface(pai), plug(pplug), thisptr_offs(pto), handler(ph), post(ppost) + { + } + Entry() + { + } + }; + private: + // Internally, hookid 1 is stored as m_Entries[0] + + CVector m_Entries; + public: + CHookIDManager(); + int New(const CProto &proto, int vtbl_offs, int vtbl_idx, void *vfnptr, void *adjustediface, + Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post); + bool Remove(int hookid); + const Entry * QueryHook(int hookid); + + // Finds all hooks with the given info, and fills the hookids into output. + void FindAllHooks(CVector &output, const CProto &proto, int vtbl_offs, int vtbl_idx, + void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post); + + // Removes all hooks with a specified vfnptr + bool RemoveAll(void *vfnptr); + }; + + struct HookInfo + { + ISHDelegate *handler; //!< Pointer to the handler + bool paused; //!< If true, the hook should not be executed + Plugin plug; //!< The owner plugin + int thisptr_offs; //!< This pointer offset + int hookid; //!< Unique ID given by CHookIDManager + + bool operator==(int otherid) + { + return hookid == otherid; + } + }; + + class CHookList : public IHookList + { + public: + List *m_VPList; // left-hand list for ListCatIterator -> for VP hooks + List m_List; + + friend class CIter; + + class CIter : public IHookList::IIter + { + friend class CHookList; + + CHookList *m_pList; + + void SkipPaused(); + public: + + ListCatIterator m_Iter; + + CIter(CHookList *pList); + + virtual ~CIter(); + + void GoToBegin(); + void Set(CIter *pOther); + + bool End(); + void Next(); + ISHDelegate *Handler(); + int ThisPtrOffs(); + + void Clear(); + + CIter *m_pNext; // When stored in m_FreeIters and m_UsedIters + CIter *m_pPrev; // Only used when stored in m_UsedIters + }; + + CIter *m_FreeIters; + CIter *m_UsedIters; // The last returned and not-yet-released iter is always m_UsedIters + + // For recalls + bool m_Recall; + bool m_RQFlag; + + void SetRecallState(); // Sets the list into a state where the next returned + // iterator (from GetIter) will be a copy of the last + // returned iterator, incremented by one. This is used in Recalls. + // The hook resets this state automatically on: + // GetIter, ReleaseIter + + void RQFlagReset() { m_RQFlag = false; } + bool RQFlagGet() { return m_RQFlag; } + CHookList(); + CHookList(const CHookList &other); + virtual ~CHookList(); + + void operator=(const CHookList &other); + + IIter *GetIter(); + void ReleaseIter(IIter *pIter); + + void SetVPList(List *newList); + void ClearVPList(); + }; + + // I know, data hiding... But I'm a lazy bastard! + + class CIface : public IIface + { + public: + void *m_Ptr; + CHookList m_PreHooks; + CHookList m_PostHooks; + public: + CIface(void *ptr); + virtual ~CIface(); + + void *GetPtr(); + IHookList *GetPreHooks(); + IHookList *GetPostHooks(); + + bool operator==(void *ptr) + { + return m_Ptr == ptr; + } + bool operator!=(void *ptr) + { + return m_Ptr != ptr; + } + }; + + class CVfnPtr : public IVfnPtr + { + public: + typedef List IfaceList; + typedef IfaceList::iterator IfaceListIter; + + void *m_Ptr; + void *m_OrigEntry; + + IfaceList m_Ifaces; + + void **m_pOneIgnore; + public: + CVfnPtr(void *ptr, void **pOneIgnore); + virtual ~CVfnPtr(); + + void *GetVfnPtr(); + void *GetOrigEntry(); + + virtual IIface *FindIface(void *ptr); + + bool operator==(void *ptr) + { + return m_Ptr == ptr; + } + }; + + class CHookManagerInfo : public IHookManagerInfo + { + public: + typedef List VfnPtrList; + typedef VfnPtrList::iterator VfnPtrListIter; + + Plugin m_Plug; + HookManagerPubFunc m_Func; + + int m_VtblOffs; + int m_VtblIdx; + const char *m_Proto; + void *m_HookfuncVfnptr; + + VfnPtrList m_VfnPtrs; + + int m_HookManVersion; + public: + CHookManagerInfo(); + virtual ~CHookManagerInfo(); + + IVfnPtr *FindVfnPtr(void *vfnptr); + + void SetInfo(int vtbl_offs, int vtbl_idx, const char *proto); + void SetHookfuncVfnptr(void *hookfunc_vfnptr); + + void SetVersion(int version); + + bool operator < (const CHookManagerInfo &other) + { + return m_HookManVersion < other.m_HookManVersion; + } + + struct Descriptor + { + Descriptor(Plugin pplug, HookManagerPubFunc ppubFunc) : plug(pplug), pubFunc(ppubFunc) + { + } + + Plugin plug; + HookManagerPubFunc pubFunc; + }; + + bool operator == (const Descriptor desc) + { + return m_Func == desc.pubFunc && m_Plug == desc.plug; + } + }; + + typedef List HookManInfoList; + + class CHookManagerContainer : public HookManInfoList + { + public: + // HMCI (Hook Manager Container Identification) + class HMCI + { + CProto m_Proto; + int m_VtableOffset; + int m_VtableIndex; + public: + HMCI(const char *proto, int vtbloffs, int vtblidx) : + m_Proto(proto), m_VtableOffset(vtbloffs), m_VtableIndex(vtblidx) + { + } + ~HMCI() + { + } + + bool operator==(const HMCI &other) const + { + return + other.m_VtableIndex == m_VtableIndex && + other.m_Proto == m_Proto && + other.m_VtableOffset == m_VtableOffset; + } + + const CProto &GetProto() const + { + return m_Proto; + } + int GetVtableOffset() const + { + return m_VtableOffset; + } + int GetVtableIndex() const + { + return m_VtableIndex; + } + }; + HMCI m_HCMI; + + public: + CHookManagerContainer(const HMCI &hmci) : m_HCMI(hmci) + { + } + bool operator == (const HMCI &other) const + { + return m_HCMI == other; + } + void AddHookManager(Plugin plug, const CHookManagerInfo &hookman); + }; + + class CCallClassImpl : public DeprecatedCallClass + { + public: + + typedef SourceHook::CVector OrigFuncs; + typedef SourceHook::THash OrigVTables; + + void *m_Ptr; //!< Pointer to the actual object + size_t m_ObjSize; //!< Size of the instance + OrigVTables m_VT; //!< Info about vtables & functions + + int m_RefCounter; + + CCallClassImpl(void *ptr, size_t size); + virtual ~CCallClassImpl(); + + bool operator==(void *other) + { + return m_Ptr == other; + } + + void *GetThisPtr(); + void *GetOrigFunc(int vtbloffs, int vtblidx); + + void ApplyCallClassPatch(int vtbl_offs, int vtbl_idx, void *orig_entry); + void RemoveCallClassPatch(int vtbl_offs, int vtbl_idx); + }; + + /** + * @brief A list of CallClass structures + */ + typedef List Impl_CallClassList; + + Impl_CallClassList m_CallClasses; //!< A list of already generated callclasses + + /** + * @brief A list of CHookManagerContainers + */ + typedef List HookManContList; + + HookManContList m_HookMans; //!< A list of hook managers + + struct HookLoopInfo + { + enum RecallType + { + Recall_No=0, + Recall_Pre, + Recall_Post1, + Recall_Post2 + }; + + META_RES *pStatus; + META_RES *pPrevRes; + META_RES *pCurRes; + + META_RES temporaryStatus; //!< Stored during Post1 recall phase + bool shouldContinue; + RecallType recall; //!< Specifies which kind of recall we're in. + + IIface *pCurIface; + const void *pOrigRet; + void *pOverrideRet; + void **pIfacePtrPtr; + }; + typedef CStack HookLoopInfoStack; + + void ApplyCallClassPatches(CCallClassImpl &cc); + void ApplyCallClassPatches(void *ifaceptr, int vtbl_offs, int vtbl_idx, void *orig_entry); + void RemoveCallClassPatches(void *ifaceptr, int vtbl_offs, int vtbl_idx); + + void SetPluginPaused(Plugin plug, bool paused); + + HookLoopInfoStack m_HLIStack; + CHookIDManager m_HookIDMan; + + void *m_OneIgnore; //:TODO: + bool m_IgnoreActive; + public: + CSourceHookImpl(); + virtual ~CSourceHookImpl(); + + /** + * @brief Returns the interface version + */ + int GetIfaceVersion(); + + /** + * @brief Returns the implemnetation version + */ + int GetImplVersion(); + + /** + * @brief Make sure that a plugin is not used by any other plugins anymore, and unregister all its hook managers + */ + void UnloadPlugin(Plugin plug); + + /** + * @brief Shut down the whole system, unregister all hook managers + */ + void CompleteShutdown(); + + /** + * @brief Add a hook. + * + * @return True if the function succeeded, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param iface The interface pointer + * @param ifacesize The size of the class iface points to + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + bool AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post); + + /** + * @brief Removes a hook. + * + * @return True if the function succeeded, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param iface The interface pointer + * @param thisptr_offs This pointer adjuster + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post); + + /** + * @brief Removes a hook. + * + * @ return True if the function succeeded, false otherwise + * + * @param info A RemoveHookInfo structure, describing the hook + */ + bool RemoveHook(RemoveHookInfo info); + + /** + * @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins + * + * @param plug The unique identifier of the plugin in question + */ + bool IsPluginInUse(Plugin plug); + + /** + * @brief Pauses all hooks of a plugin + * + * @param plug The unique identifier of the plugin + */ + void PausePlugin(Plugin plug); + + /** + * @brief Unpauses all hooks of a plugin + * + * @param plug The unique identifier of the plugin + */ + void UnpausePlugin(Plugin plug); + + /** + * @brief Return a pointer to a callclass. Generate a new one if required. + * + * @param iface The interface pointer + * @param size Size of the class instance + */ + DeprecatedCallClass *GetCallClass(void *iface, size_t size); + + /** + * @brief Release a callclass + * + * @param ptr Pointer to the callclass + */ + virtual void ReleaseCallClass(DeprecatedCallClass *ptr); + + virtual void SetRes(META_RES res); //!< Sets the meta result + virtual META_RES GetPrevRes(); //!< Gets the meta result of the previously called handler + virtual META_RES GetStatus(); //!< Gets the highest meta result + virtual const void *GetOrigRet(); //!< Gets the original result. If not in post function, undefined + virtual const void *GetOverrideRet(); //!< Gets the override result. If none is specified, NULL + virtual void *GetIfacePtr(); //!< Gets the interface pointer + + ////////////////////////////////////////////////////////////////////////// + // For hook managers + void HookLoopBegin(IIface *pIface); //!< Should be called when a hook loop begins + void HookLoopEnd(); //!< Should be called when a hook loop exits + void SetCurResPtr(META_RES *mres); //!< Sets pointer to the current meta result + void SetPrevResPtr(META_RES *mres); //!< Sets pointer to previous meta result + void SetStatusPtr(META_RES *mres); //!< Sets pointer to the status variable + void SetIfacePtrPtr(void **pp); //!< Sets pointer to the interface this pointer + void SetOrigRetPtr(const void *ptr); //!< Sets the original return pointer + void SetOverrideRetPtr(void *ptr); //!< Sets the override result pointer + bool ShouldContinue(); //!< Returns false if the hook loop should exit + + /** + * @brief Remove a hook manager. Auto-removes all hooks attached to it from plugin plug. + * + * @param plug The owner of the hook manager + * @param pubFunc The hook manager's info function + */ + virtual void RemoveHookManager(Plugin plug, HookManagerPubFunc pubFunc); + virtual void RemoveHookManager(RemoveHookManInfo info); + + virtual void DoRecall(); //!< Initiates a recall sequence + virtual void *GetOverrideRetPtr(); //!< Returns the pointer set by SetOverrideRetPtr + + virtual void *SetupHookLoop(META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr, + void **ifacePtrPtr, const void *origRetPtr, void *overrideRetPtr); + + /** + * @brief Add a (VP) hook. + * + * @return non-zero hook id on success, 0 otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param mode Can be either Hook_Normal or Hook_VP (vtable-wide hook) + * @param iface The interface pointer + * The representative interface pointer for VP hooks + * The vtable pointer for direct VP hooks !!! + * @param ifacesize The size of the class iface points to + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + virtual int AddHookNew(Plugin plug, AddHookMode mode, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, + ISHDelegate *handler, bool post); + + /** + * @brief Remove a VP hook by ID. + * + * @return true on success, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param hookid The hook id (returned by AddHookNew) + */ + virtual bool RemoveHookByID(Plugin plug, int hookid); + + /** + * @brief Makes sure that hooks are going to be ignored on the next call of vfnptr + * + * @param plug The unique identifier of the plugin that calls this function + * @param vfnptr The virtual function pointer of the function in question + */ + virtual void SetIgnoreHooks(Plugin plug, void *vfnptr); + + /** + * @brief Reverses SetIgnoreHooks' effect + * + * @param plug The unique identifier of the plugin that calls this function + * @param vfnptr The virtual function pointer of the function in question + */ + virtual void ResetIgnoreHooks(Plugin plug, void *vfnptr); + + /** + * @brief Finds the original entry of a virtual function pointer + * + * @param vfnptr The virtual function pointer + * @return The original entry if the virtual function pointer has been patched; NULL otherwise. + */ + virtual void *GetOrigVfnPtrEntry(void *vfnptr); + }; +} + +#endif diff --git a/utils/mmsource/core-legacy/sourcehook/test/Makefile b/utils/mmsource/core-legacy/sourcehook/test/Makefile new file mode 100644 index 00000000..6c859b03 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/Makefile @@ -0,0 +1,63 @@ +#(C)2004-2007 SourceMM Development Team +# Makefile written by David "BAILOPAN" Anderson and Pavol Marko + +OPT_FLAGS = -O3 -funroll-loops -s -pipe +DEBUG_FLAGS = -g -ggdb3 +CPP = gcc +LINK = -lstdc++ +INCLUDE = -I. -I.. +MAX_PARAMS=20 + +BINARY = sourcehook_test +OBJECTS = main.cpp sourcehook.cpp $(shell ls -t test*.cpp) +HEADERS = ../sh_list.h ../sh_tinyhash.h ../sh_memory.h ../sh_string.h ../sh_vector.h ../sourcehook_impl.h ../FastDelegate.h ../sourcehook.h ../sh_memfuncinfo.h + +ifeq "$(DEBUG)" "true" + BIN_DIR = Debug + CFLAGS = $(DEBUG_FLAGS) +else + BIN_DIR = Release + CFLAGS = $(OPT_FLAGS) +endif + +CFLAGS += -Wall +# Also, enable SH_ASSERT +CFLAGS += -DSH_DEBUG + +OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) + + +default: all + +$(BIN_DIR)/%.o: %.cpp $(HEADERS) + $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< + +../sourcehook.h: ../generate/sourcehook.hxx + (cd ../generate; ./shworker.bin iter sourcehook.hxx sourcehook.h $(MAX_PARAMS); cp sourcehook.h ..) + +../sourcehook.hxx: ../generate/sh_memfuncinfo.hxx + (cd ../generate; ./shworker.bin iter sh_memfuncinfo.hxx sh_memfuncinfo.h $(MAX_PARAMS); cp sh_memfuncino.h ..) + +../FastDelegate.hxx: ../generate/FastDelegate.hxx + (cd ../generate; ./shworker.bin iter FastDelegate.hxx FastDelegate.h $(MAX_PARAMS); cp FastDelegate.h ..) + +debug: + $(MAKE) all DEBUG=true + +all: + mkdir -p $(BIN_DIR) + ln -sf ../sourcehook.cpp sourcehook.cpp + $(MAKE) $(BINARY) + rm -f $(BINARY) + rm -f sourcehook.cpp + ln -sf $(BIN_DIR)/$(BINARY) $(BINARY) + + +$(BINARY): $(OBJ_LINUX) + $(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -o$(BIN_DIR)/$(BINARY) + +clean: + rm -rf Release/*.o + rm -rf Release/$(BINARY) + rm -rf Debug/*.o + rm -rf Debug/$(BINARY) diff --git a/utils/mmsource/core-legacy/sourcehook/test/main.cpp b/utils/mmsource/core-legacy/sourcehook/test/main.cpp new file mode 100644 index 00000000..aa0147dd --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/main.cpp @@ -0,0 +1,132 @@ +// Hello BAIL! +// hello pm how are you +// I'm fine, what about you? +// not bad, just looking for mem leaks +// mem leaks in my code!? never! I have to preserve binary compatibility :( +// This is a test file + +#include +#include +#include +#include +#include +#include "sh_tinyhash.h" +#include "sh_list.h" +#include "sourcehook_impl.h" +#include "sourcehook.h" + +using namespace std; + +bool g_Verbose; + +class Test +{ + typedef bool (*TestProto)(std::string&); + TestProto m_Func; + std::string m_Name; + + static SourceHook::List ms_Tests; +public: + Test(TestProto func, const char *name) : m_Func(func), m_Name(name) + { + ms_Tests.push_back(this); + } + + bool operator()() + { + std::string error; + if (!m_Func(error)) + { + cout << "Test" << m_Name << " FAILED: " << error << endl; + return false; + } + else + { + cout << "Test" << m_Name << " passed" << endl; + return true; + } + } + + static void DoTests() + { + int passed=0, failed=0; + for (SourceHook::List::iterator iter = ms_Tests.begin(); iter != ms_Tests.end(); ++iter) + { + if ((**iter)()) + ++passed; + else + ++failed; + } + cout << endl << "----" << endl << "Passed: " << passed << endl << "Failed: " << failed << endl; + cout << "Total: " << passed + failed << endl; + } +}; + +SourceHook::List Test::ms_Tests; + +#define DO_TEST(x) \ + bool Test##x(std::string &error); \ + Test g_Test##x(Test##x, #x); + +DO_TEST(List); +DO_TEST(Basic); +DO_TEST(VafmtAndOverload); +DO_TEST(ThisPtrOffs); +DO_TEST(PlugSys); +DO_TEST(Bail); +DO_TEST(Reentr); +DO_TEST(Manual); +DO_TEST(Recall); +DO_TEST(Multi); +DO_TEST(Ref); +DO_TEST(RefRet); +DO_TEST(VPHooks); + +int main(int argc, char *argv[]) +{ + std::string error; + + g_Verbose = argc > 1 && strcmp(argv[1], "-v") == 0; + + Test::DoTests(); + + cout << "Press enter to continue" << endl; + + char x; + cin.read(&x, 1); +} + +SourceHook::ISourceHook *Test_Factory() +{ + return new SourceHook::CSourceHookImpl(); +} + +void Test_Delete(SourceHook::ISourceHook *shptr) +{ + delete static_cast(shptr); +} + +void Test_CompleteShutdown(SourceHook::ISourceHook *shptr) +{ + static_cast(shptr)->CompleteShutdown(); +} + +bool Test_IsPluginInUse(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + return static_cast(shptr)->IsPluginInUse(plug); +} + +void Test_UnloadPlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + static_cast(shptr)->UnloadPlugin(plug); +} + +void Test_PausePlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + static_cast(shptr)->PausePlugin(plug); +} + +void Test_UnpausePlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) +{ + static_cast(shptr)->UnpausePlugin(plug); +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/msvc7/test.vcproj b/utils/mmsource/core-legacy/sourcehook/test/msvc7/test.vcproj new file mode 100644 index 00000000..d6ce1366 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/msvc7/test.vcproj @@ -0,0 +1,374 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/utils/mmsource/core-legacy/sourcehook/test/msvc8/test.vcproj b/utils/mmsource/core-legacy/sourcehook/test/msvc8/test.vcproj new file mode 100644 index 00000000..d843564c --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/msvc8/test.vcproj @@ -0,0 +1,517 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/utils/mmsource/core-legacy/sourcehook/test/sourcehook_test.h b/utils/mmsource/core-legacy/sourcehook/test/sourcehook_test.h new file mode 100644 index 00000000..9d914b4e --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/sourcehook_test.h @@ -0,0 +1,27 @@ +// This file is used for backwards compatibility testing +// It allows us to test binary backwards compatibility by using an older include file HERE: +#include "sourcehook.h" // <-- here +// There. main.cpp which implements all of the following function is always usign sourcehook.h +// and the up-to-date sourcehook_impl.h/sourcehook.cpp. The tests use this file however. +// If the test needs an up-to-date version (like the recall test), it can simply +// #include "sourcehook.h" before including this, thus overriding our decision. + + +SourceHook::ISourceHook *Test_Factory(); +void Test_Delete(SourceHook::ISourceHook *shptr); + +struct CSHPtrAutoDestruction +{ + SourceHook::ISourceHook *m_SHPtr; + CSHPtrAutoDestruction(SourceHook::ISourceHook *shptr) : m_SHPtr(shptr) {} + ~CSHPtrAutoDestruction() { Test_Delete(m_SHPtr); } +}; + +#define GET_SHPTR(var) var = Test_Factory(); CSHPtrAutoDestruction ___autodestruction(var); + +// Access to CSourceHookImpl functions +void Test_CompleteShutdown(SourceHook::ISourceHook *shptr); +bool Test_IsPluginInUse(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug); +void Test_UnloadPlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug); +void Test_PausePlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug); +void Test_UnpausePlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug); diff --git a/utils/mmsource/core-legacy/sourcehook/test/test1.cpp b/utils/mmsource/core-legacy/sourcehook/test/test1.cpp new file mode 100644 index 00000000..6632090a --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/test1.cpp @@ -0,0 +1,723 @@ +#include +#include "sourcehook_test.h" +#include "testevents.h" + +#include "sh_memory.h" + +namespace +{ + StateList g_States; + SourceHook::ISourceHook *g_SHPtr; + SourceHook::Plugin g_PLID; + + // TEST1 + // Basic tests + // Hooking and callclass + + MAKE_STATE_1(State_ModuleInMemory, bool); + MAKE_STATE(State_F1_Called); + MAKE_STATE_1(State_F1_PreHandler_Called, void*); + MAKE_STATE_1(State_F1_PostHandler_Called, void*); + MAKE_STATE_1(State_F1_HookAdded, bool); + MAKE_STATE(State_F1_HookRemoved); + MAKE_STATE(State_F1_CallClassGenerated); + MAKE_STATE(State_F1_CallClassReleased); + MAKE_STATE_1(State_F299_Called, std::string); + MAKE_STATE_1(State_F299_PreHandlerCalled, std::string); + MAKE_STATE_1(State_F299_PostHandlerCalled, std::string); + MAKE_STATE_1(State_F299Ret, bool); + + class Test + { + public: + virtual void F1() + { + ADD_STATE(State_F1_Called); + } + virtual void F2(){} + virtual void F3(){} + virtual void F4(){} + virtual void F5(){} + virtual void F6(){} + virtual void F7(){} + virtual void F8(){} + virtual void F9(){} + virtual void F10(){} + virtual void F11(){} + virtual void F12(){} + virtual void F13(){} + virtual void F14(){} + virtual void F15(){} + virtual void F16(){} + virtual void F17(){} + virtual void F18(){} + virtual void F19(){} + virtual float F20() const { return 1.0f; } // Look! F20 is const-ed and returns a float + virtual void F21(){} + virtual void F22(){} + virtual void F23(){} + virtual void F24(){} + virtual void F25(){} + virtual void F26(){} + virtual void F27(){} + virtual void F28(){} + virtual void F29(){} + virtual void F30(){} + virtual void F31(){} + virtual void F32(){} + virtual void F33(){} + virtual void F34(){} + virtual void F35(){} + virtual void F36(){} + virtual void F37(){} + virtual void F38(){} + virtual void F39(){} + virtual void F40(){} + virtual void F41(){} + virtual void F42(){} + virtual void F43(){} + virtual void F44(){} + virtual void F45(){} + virtual void F46(){} + virtual void F47(){} + virtual void F48(){} + virtual void F49(){} + virtual void F50(){} + virtual void F51(){} + virtual void F52(){} + virtual void F53(){} + virtual void F54(){} + virtual void F55(){} + virtual void F56(){} + virtual void F57(){} + virtual void F58(){} + virtual void F59(){} + virtual void F60(int &hello){} + virtual void F61(){} + virtual void F62(){} + virtual void F63(){} + virtual void F64(){} + virtual void F65(){} + virtual void F66(){} + virtual void F67(){} + virtual void F68(){} + virtual void F69(){} + virtual void F70(){} + virtual void F71(){} + virtual void F72(){} + virtual void F73(){} + virtual void F74(){} + virtual void F75(){} + virtual void F76(){} + virtual void F77(){} + virtual void F78(){} + virtual void F79(){} + virtual void F80(){} + virtual void F81(){} + virtual void F82(){} + virtual void F83(){} + virtual void F84(){} + virtual void F85(){} + virtual void F86(){} + virtual void F87(){} + virtual void F88(){} + virtual void F89(){} + virtual void F90(){} + virtual void F91(){} + virtual void F92(){} + virtual void F93(){} + virtual void F94(){} + virtual void F95(){} + virtual void F96(){} + virtual void F97(){} + virtual void F98(){} + virtual void F99(){} + virtual void F100(){} + virtual void F101(){} + virtual void F102(){} + virtual void F103(){} + virtual void F104(){} + virtual void F105(){} + virtual void F106(){} + virtual void F107(){} + virtual void F108(){} + virtual void F109(){} + virtual void F110(){} + virtual void F111(){} + virtual void F112(){} + virtual void F113(){} + virtual void F114(){} + virtual void F115(){} + virtual void F116(){} + virtual void F117(){} + virtual void F118(){} + virtual void F119(){} + virtual void F120(){} + virtual void F121(){} + virtual void F122(){} + virtual void F123(){} + virtual void F124(){} + virtual void F125(){} + virtual void F126(){} + virtual void F127(){} + virtual void F128(){} + virtual void F129(){} + virtual void F130(){} + virtual void F131(){} + virtual void F132(){} + virtual void F133(){} + virtual void F134(){} + virtual void F135(){} + virtual void F136(){} + virtual void F137(){} + virtual void F138(){} + virtual void F139(){} + virtual void F140(){} + virtual void F141(){} + virtual void F142(){} + virtual void F143(){} + virtual void F144(){} + virtual void F145(){} + virtual void F146(){} + virtual void F147(){} + virtual void F148(){} + virtual void F149(){} + virtual void F150(){} + virtual void F151(){} + virtual void F152(){} + virtual void F153(){} + virtual void F154(){} + virtual void F155(){} + virtual void F156(){} + virtual void F157(){} + virtual void F158(){} + virtual void F159(){} + virtual void F160(){} + virtual void F161(){} + virtual void F162(){} + virtual void F163(){} + virtual void F164(){} + virtual void F165(){} + virtual void F166(){} + virtual void F167(){} + virtual void F168(){} + virtual void F169(){} + virtual void F170(){} + virtual void F171(){} + virtual void F172(){} + virtual void F173(){} + virtual void F174(){} + virtual void F175(){} + virtual void F176(){} + virtual void F177(){} + virtual void F178(){} + virtual void F179(){} + virtual void F180(){} + virtual void F181(){} + virtual void F182(){} + virtual void F183(){} + virtual void F184(){} + virtual void F185(){} + virtual void F186(){} + virtual void F187(){} + virtual void F188(){} + virtual void F189(){} + virtual void F190(){} + virtual void F191(){} + virtual void F192(){} + virtual void F193(){} + virtual void F194(){} + virtual void F195(){} + virtual void F196(){} + virtual void F197(){} + virtual void F198(){} + virtual void F199(){} + virtual void F200(){} + virtual void F201(){} + virtual void F202(){} + virtual void F203(){} + virtual void F204(){} + virtual void F205(){} + virtual void F206(){} + virtual void F207(){} + virtual void F208(){} + virtual void F209(){} + virtual void F210(){} + virtual void F211(){} + virtual void F212(){} + virtual void F213(){} + virtual void F214(){} + virtual void F215(){} + virtual void F216(){} + virtual void F217(){} + virtual void F218(){} + virtual void F219(){} + virtual void F220(){} + virtual void F221(){} + virtual void F222(){} + virtual void F223(){} + virtual void F224(){} + virtual void F225(){} + virtual void F226(){} + virtual void F227(){} + virtual void F228(){} + virtual void F229(){} + virtual void F230(){} + virtual void F231(){} + virtual void F232(){} + virtual void F233(){} + virtual void F234(){} + virtual void F235(){} + virtual void F236(){} + virtual void F237(){} + virtual void F238(){} + virtual void F239(){} + virtual void F240(){} + virtual void F241(){} + virtual void F242(){} + virtual void F243(){} + virtual void F244(){} + virtual void F245(){} + virtual void F246(){} + virtual void F247(){} + virtual void F248(){} + virtual void F249(){} + virtual void F250(){} + virtual void F251(){} + virtual void F252(){} + virtual void F253(){} + virtual void F254(){} + virtual void F255(){} + virtual void F256(){} + virtual void F257(){} + virtual void F258(){} + virtual void F259(){} + virtual void F260(){} + virtual void F261(){} + virtual void F262(){} + virtual void F263(){} + virtual void F264(){} + virtual void F265(){} + virtual void F266(){} + virtual void F267(){} + virtual void F268(){} + virtual void F269(){} + virtual void F270(){} + virtual void F271(){} + virtual void F272(){} + virtual void F273(){} + virtual void F274(){} + virtual void F275(){} + virtual void F276(){} + virtual void F277(){} + virtual void F278(){} + virtual void F279(){} + virtual void F280(){} + virtual void F281(){} + virtual void F282(){} + virtual void F283(){} + virtual void F284(){} + virtual void F285(){} + virtual void F286(){} + virtual void F287(){} + virtual void F288(){} + virtual void F289(){} + virtual void F290(){} + virtual void F291(){} + virtual void F292(){} + virtual void F293(){} + virtual void F294(){} + virtual void F295(){} + virtual void F296(){} + virtual void F297(){} + virtual void F298(){} + virtual bool F299(const char *mwah) + { + ADD_STATE(State_F299_Called(mwah)); + return true; + } + }; + + // GCC's optimizer is too good. I had to add this in order to make it execute a virtual table lookup! + class Whatever : public Test + { + }; + + SH_DECL_HOOK1(Test, F299, SH_NOATTRIB, 0, bool, const char *); + SH_DECL_HOOK0_void(Test, F1, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Test, F2, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Test, F3, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Test, F4, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Test, F5, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Test, F6, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Test, F7, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Test, F8, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Test, F9, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Test, F10, SH_NOATTRIB, 0); + + SH_DECL_HOOK0(Test, F20, const, 0, float); + SH_DECL_HOOK1_void(Test, F60, SH_NOATTRIB, 0, int&); + + META_RES g_F1Pre_WhatToDo; + META_RES g_F1Post_WhatToDo; + + struct HandlersF1 + { + void Pre() + { + ADD_STATE(State_F1_PreHandler_Called(reinterpret_cast(this))); + RETURN_META(g_F1Pre_WhatToDo); + } + + void Post() + { + ADD_STATE(State_F1_PostHandler_Called(reinterpret_cast(this))); + RETURN_META(g_F1Post_WhatToDo); + } + }; + + META_RES g_F299Pre_WhatToDo; + bool g_F299Pre_WhatToRet; + + bool F299_Pre(const char *mwah) + { + ADD_STATE(State_F299_PreHandlerCalled(mwah)); + RETURN_META_VALUE(g_F299Pre_WhatToDo, g_F299Pre_WhatToRet); + } + + bool F299_Post(const char *mwah) + { + ADD_STATE(State_F299_PostHandlerCalled(mwah)); + RETURN_META_VALUE(MRES_OVERRIDE, META_RESULT_STATUS >= MRES_OVERRIDE ? !META_RESULT_OVERRIDE_RET(bool) : + !META_RESULT_ORIG_RET(bool)); + } + + void F60_Pre(int &hello) + { + hello = 10; + } +} + +template T func(T a) +{ + return a; +} + + +bool TestBasic(std::string &error) +{ + // Simple test for ModuleInMemory + // 1) &error should on the stack + // 2) 0 should not be mapped + ADD_STATE(State_ModuleInMemory(SourceHook::ModuleInMemory(reinterpret_cast(&error), sizeof(error)))); + ADD_STATE(State_ModuleInMemory(SourceHook::ModuleInMemory(0, 1))); + + CHECK_STATES((&g_States, + new State_ModuleInMemory(true), + new State_ModuleInMemory(false), + NULL), "ModuleInMemory"); + + GET_SHPTR(g_SHPtr); + g_PLID = 1337; + + HandlersF1 f1_handlers; + Whatever test; + Test *pTest = &test; + + // 1) SH_CALL it and call it normally + + SH_CALL(pTest, &Test::F1)(); + + pTest->F1(); + + CHECK_STATES((&g_States, + new State_F1_Called, + new State_F1_Called, + NULL), "Part 1"); + + // 2) Request a call class again + + SH_CALL(pTest, &Test::F1)(); + SH_CALL(pTest, &Test::F1)(); + pTest->F1(); + + SH_CALL(pTest, &Test::F1)(); + pTest->F1(); + + CHECK_STATES((&g_States, + new State_F1_Called, + new State_F1_Called, + new State_F1_Called, + + new State_F1_Called, + new State_F1_Called, + NULL), "Part 2"); + + // 3) Add a pre hook + // (one add memfunc in old format) + g_F1Pre_WhatToDo = MRES_SUPERCEDE; + ADD_STATE(State_F1_HookAdded(SH_ADD_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Pre, false) ? true : false)); + + SH_CALL(pTest, &Test::F1)(); + pTest->F1(); + + CHECK_STATES((&g_States, + new State_F1_HookAdded(true), + new State_F1_Called, + new State_F1_PreHandler_Called(&f1_handlers), + NULL), "Part 3"); + + // 4) Test source-level compat with callclasses + SourceHook::CallClass *pCC = SH_GET_CALLCLASS(pTest); + + // bug 4210 + SH_CALL(pCC, &Test::F1)(); + + CHECK_STATES((&g_States, + new State_F1_Called, + NULL), "bug 4210"); + + SH_CALL(pCC, &Test::F1)(); + pTest->F1(); + + CHECK_STATES((&g_States, + new State_F1_Called, + new State_F1_PreHandler_Called(&f1_handlers), + NULL), "Part 4"); + + SH_RELEASE_CALLCLASS(pCC); + + // 5) Check ignore / supercede + g_F1Pre_WhatToDo = MRES_SUPERCEDE; + SH_CALL(pTest, &Test::F1)(); + pTest->F1(); + + g_F1Pre_WhatToDo = MRES_IGNORED; + SH_CALL(pTest, &Test::F1)(); + pTest->F1(); + + CHECK_STATES((&g_States, + new State_F1_Called, + new State_F1_PreHandler_Called(&f1_handlers), + new State_F1_Called, + new State_F1_PreHandler_Called(&f1_handlers), + new State_F1_Called, + NULL), "Part 5"); + + // 6) remove the hook again + // (one remove memfunc in old format) + SH_REMOVE_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Pre, false); + ADD_STATE(State_F1_HookRemoved); + + SH_CALL(pTest, &Test::F1)(); + pTest->F1(); + + CHECK_STATES((&g_States, + new State_F1_HookRemoved, + new State_F1_Called, + new State_F1_Called, + NULL), "Part 6"); + + // 7) add a post hook now + g_F1Post_WhatToDo = MRES_IGNORED; + ADD_STATE(State_F1_HookAdded(SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Post), true) ? true : false)); + + SH_CALL(pTest, &Test::F1)(); + pTest->F1(); + + CHECK_STATES((&g_States, + new State_F1_HookAdded(true), + new State_F1_Called, + new State_F1_Called, + new State_F1_PostHandler_Called(&f1_handlers), + NULL), "Part 7"); + + // 8) And a pre hook again + g_F1Pre_WhatToDo = MRES_IGNORED; + ADD_STATE(State_F1_HookAdded(SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false) ? true : false)); + + SH_CALL(pTest, &Test::F1)(); + pTest->F1(); + + g_F1Pre_WhatToDo = MRES_SUPERCEDE; + SH_CALL(pTest, &Test::F1)(); + pTest->F1(); + + CHECK_STATES((&g_States, + new State_F1_HookAdded(true), + new State_F1_Called, + new State_F1_PreHandler_Called(&f1_handlers), + new State_F1_Called, + new State_F1_PostHandler_Called(&f1_handlers), + new State_F1_Called, + new State_F1_PreHandler_Called(&f1_handlers), + new State_F1_PostHandler_Called(&f1_handlers), + NULL), "Part 8"); + + // 9) Remove all hooks + SH_REMOVE_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + ADD_STATE(State_F1_HookRemoved); + SH_REMOVE_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Post), true); + ADD_STATE(State_F1_HookRemoved); + + SH_CALL(pTest, &Test::F1)(); + pTest->F1(); + + CHECK_STATES((&g_States, + new State_F1_HookRemoved, + new State_F1_HookRemoved, + new State_F1_Called, + new State_F1_Called, + NULL), "Part 9"); + + // 10) Some checks on F299 + g_F299Pre_WhatToDo = MRES_IGNORED; + g_F299Pre_WhatToRet = false; + + ADD_STATE(State_F299Ret(pTest->F299("hi"))); + ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi"))); + + CHECK_STATES((&g_States, + new State_F299_Called("hi"), + new State_F299Ret(true), + new State_F299_Called("hi"), + new State_F299Ret(true), + NULL), "Part 10.1"); + + // (one add staticfunc in old format) + SH_ADD_HOOK_STATICFUNC(Test, F299, pTest, F299_Pre, false); + ADD_STATE(State_F299Ret(pTest->F299("hi"))); + ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi"))); + + CHECK_STATES((&g_States, + new State_F299_PreHandlerCalled("hi"), + new State_F299_Called("hi"), + new State_F299Ret(true), + new State_F299_Called("hi"), + new State_F299Ret(true), + NULL), "Part 10.2"); + + SH_ADD_HOOK(Test, F299, pTest, SH_STATIC(F299_Post), true); + ADD_STATE(State_F299Ret(pTest->F299("hi"))); + ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi"))); + + CHECK_STATES((&g_States, + new State_F299_PreHandlerCalled("hi"), + new State_F299_Called("hi"), + new State_F299_PostHandlerCalled("hi"), + new State_F299Ret(false), + new State_F299_Called("hi"), + new State_F299Ret(true), + NULL), "Part 10.3"); + + g_F299Pre_WhatToDo = MRES_OVERRIDE; + ADD_STATE(State_F299Ret(pTest->F299("hi"))); + ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi"))); + + CHECK_STATES((&g_States, + new State_F299_PreHandlerCalled("hi"), + new State_F299_Called("hi"), + new State_F299_PostHandlerCalled("hi"), + new State_F299Ret(true), + new State_F299_Called("hi"), + new State_F299Ret(true), + NULL), "Part 10.4"); + + g_F299Pre_WhatToDo = MRES_SUPERCEDE; + ADD_STATE(State_F299Ret(pTest->F299("hi"))); + ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi"))); + + CHECK_STATES((&g_States, + new State_F299_PreHandlerCalled("hi"), + new State_F299_PostHandlerCalled("hi"), + new State_F299Ret(true), + new State_F299_Called("hi"), + new State_F299Ret(true), + NULL), "Part 10.5"); + + // (one remove staticfunc in old format) + SH_REMOVE_HOOK_STATICFUNC(Test, F299, pTest, F299_Pre, false); + ADD_STATE(State_F299Ret(pTest->F299("hi"))); + ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi"))); + + CHECK_STATES((&g_States, + new State_F299_Called("hi"), + new State_F299_PostHandlerCalled("hi"), + new State_F299Ret(false), + new State_F299_Called("hi"), + new State_F299Ret(true), + NULL), "Part 10.6"); + + SH_REMOVE_HOOK(Test, F299, pTest, SH_STATIC(F299_Post), true); + ADD_STATE(State_F299Ret(pTest->F299("hi"))); + ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi"))); + + CHECK_STATES((&g_States, + new State_F299_Called("hi"), + new State_F299Ret(true), + new State_F299_Called("hi"), + new State_F299Ret(true), + NULL), "Part 10.7"); + + + // 11 1/2) Test removing hook by id + + g_F1Pre_WhatToDo = MRES_IGNORED; + + pTest->F1(); + int hookPre = SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + int hookPost = SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Post), true); + + pTest->F1(); + SH_REMOVE_HOOK_ID(hookPost); + pTest->F1(); + SH_REMOVE_HOOK_ID(hookPre); + pTest->F1(); + + CHECK_STATES((&g_States, + new State_F1_Called, + + new State_F1_PreHandler_Called(&f1_handlers), + new State_F1_Called, + new State_F1_PostHandler_Called(&f1_handlers), + + new State_F1_PreHandler_Called(&f1_handlers), + new State_F1_Called, + + new State_F1_Called, + + NULL), "Part 11 1/2"); + + // 12) Test? Test. + SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); + SH_ADD_HOOK(Test, F2, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); + SH_ADD_HOOK(Test, F3, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + SH_ADD_HOOK(Test, F4, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); + SH_ADD_HOOK(Test, F5, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + SH_ADD_HOOK(Test, F6, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); + SH_ADD_HOOK(Test, F7, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + SH_ADD_HOOK(Test, F8, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + SH_ADD_HOOK(Test, F9, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + SH_ADD_HOOK(Test, F10, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + + SH_REMOVE_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); + SH_REMOVE_HOOK(Test, F2, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); + SH_REMOVE_HOOK(Test, F3, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + SH_REMOVE_HOOK(Test, F4, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); + SH_REMOVE_HOOK(Test, F5, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + SH_REMOVE_HOOK(Test, F6, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); + SH_REMOVE_HOOK(Test, F7, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + SH_REMOVE_HOOK(Test, F8, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + SH_REMOVE_HOOK(Test, F9, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + SH_REMOVE_HOOK(Test, F10, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); + + SH_ADD_HOOK(Test, F60, pTest, SH_STATIC(F60_Pre), false); + + int a = 0; + pTest->F60(a); + Test_CompleteShutdown(g_SHPtr); + + CHECK_COND(a == 10, "Part12.a"); + + return true; +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/test2.cpp b/utils/mmsource/core-legacy/sourcehook/test/test2.cpp new file mode 100644 index 00000000..46c988cc --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/test2.cpp @@ -0,0 +1,172 @@ +#include +#include "sourcehook_test.h" +#include "testevents.h" +#include + +// TEST2 +// Vafmt and Overloaded functions +namespace +{ + StateList g_States; + SourceHook::ISourceHook *g_SHPtr; + SourceHook::Plugin g_PLID; + + MAKE_STATE_1(State_EatYams_Called, int); + MAKE_STATE_1(State_EatYams_Handler_Called, int); + MAKE_STATE_2(State_Vafmt_Called, int, std::string); + MAKE_STATE_2(State_Vafmt_PreHandler_Called, int, std::string); + MAKE_STATE_2(State_Vafmt_PostHandler_Called, int, std::string); + + class IGaben + { + public: + virtual void EatYams() + { + ADD_STATE(State_EatYams_Called(0)); + } + virtual bool EatYams(const char *location) const + { + ADD_STATE(State_EatYams_Called(1)); + return true; + } + virtual void Vafmt1(bool param1, int x, const char *fmt, ...) + { + va_list ap; + va_start(ap, fmt); + char buffer[512]; + vsprintf(buffer, fmt, ap); + va_end(ap); + ADD_STATE(State_Vafmt_Called(1, std::string(buffer))); + } + virtual float Vafmt2(const char *fmt, ...) + { + va_list ap; + va_start(ap, fmt); + char buffer[512]; + vsprintf(buffer, fmt, ap); + va_end(ap); + ADD_STATE(State_Vafmt_Called(2, std::string(buffer))); + return 0.0f; + } + }; + + // GCC's optimizer is too good. I had to add this in order to make it execute a virtual table lookup! + class Whatever : public IGaben + { + }; + + SH_DECL_HOOK0_void(IGaben, EatYams, SH_NOATTRIB, 0); + SH_DECL_HOOK1(IGaben, EatYams, const, 1, bool, const char *); + SH_DECL_HOOK2_void_vafmt(IGaben, Vafmt1, SH_NOATTRIB, 0, bool, int); + SH_DECL_HOOK0_vafmt(IGaben, Vafmt2, SH_NOATTRIB, 0, float); + + void EatYams0_Handler() + { + ADD_STATE(State_EatYams_Handler_Called(0)); + } + + bool EatYams1_Handler(const char *loc) + { + ADD_STATE(State_EatYams_Handler_Called(1)); + return true; + } + + void Vafmt1_PreHandler(bool param1, int x, const char *in) + { + ADD_STATE(State_Vafmt_PreHandler_Called(1, std::string(in))); + } + void Vafmt1_PostHandler(bool param1, int x, const char *in) + { + ADD_STATE(State_Vafmt_PostHandler_Called(1, std::string(in))); + } + float Vafmt2_PreHandler(const char *in) + { + ADD_STATE(State_Vafmt_PreHandler_Called(2, std::string(in))); + return 0.0f; + } + float Vafmt2_PostHandler(const char *in) + { + ADD_STATE(State_Vafmt_PostHandler_Called(2, std::string(in))); + return 0.0f; + } +} + + +bool TestVafmtAndOverload(std::string &error) +{ + GET_SHPTR(g_SHPtr); + g_PLID = 1337; + + Whatever gabgab; + IGaben *pGab = &gabgab; + + // Part 1 + SH_CALL(pGab, static_cast(&IGaben::EatYams))(); + SH_CALL(pGab, static_cast(&IGaben::EatYams))("Here!"); + + SH_ADD_HOOK(IGaben, EatYams, pGab, EatYams0_Handler, false); + SH_ADD_HOOK(IGaben, EatYams, pGab, EatYams1_Handler, false); + + pGab->EatYams(); + pGab->EatYams("Here!"); + + SH_REMOVE_HOOK(IGaben, EatYams, pGab, EatYams0_Handler, false); + SH_REMOVE_HOOK(IGaben, EatYams, pGab, EatYams1_Handler, false); + + CHECK_STATES((&g_States, + new State_EatYams_Called(0), + new State_EatYams_Called(1), + new State_EatYams_Handler_Called(0), + new State_EatYams_Called(0), + new State_EatYams_Handler_Called(1), + new State_EatYams_Called(1), + NULL),"Part 1"); + + // Part 2 + pGab->Vafmt1(true, 55, "Hello %s%d%s", "BA", 1, "L"); + SH_CALL(pGab, &IGaben::Vafmt1)(true, 55, "Hello %s%d%s", "BA", 1, "L"); + pGab->Vafmt2("Hello %s%d%s", "BA", 1, "LOPAN"); + SH_CALL(pGab, &IGaben::Vafmt2)("Hello %s%d%s", "BA", 1, "LOPAN"); + + CHECK_STATES((&g_States, + new State_Vafmt_Called(1, "Hello BA1L"), + new State_Vafmt_Called(1, "Hello BA1L"), + new State_Vafmt_Called(2, "Hello BA1LOPAN"), + new State_Vafmt_Called(2, "Hello BA1LOPAN"), + NULL), "Part 2"); + + // Part 3 + SH_ADD_HOOK(IGaben, Vafmt1, pGab, Vafmt1_PreHandler, false); + SH_ADD_HOOK(IGaben, Vafmt1, pGab, Vafmt1_PostHandler, true); + SH_ADD_HOOK(IGaben, Vafmt2, pGab, Vafmt2_PreHandler, false); + SH_ADD_HOOK(IGaben, Vafmt2, pGab, Vafmt2_PostHandler, true); + + pGab->Vafmt1(true, 55, "Hello %s%d%s", "BA", 1, "L"); + pGab->Vafmt2("Hello %s%d%s", "BA", 1, "LOPAN"); + + CHECK_STATES((&g_States, + new State_Vafmt_PreHandler_Called(1, std::string("Hello BA1L")), + new State_Vafmt_Called(1, std::string("Hello BA1L")), + new State_Vafmt_PostHandler_Called(1, std::string("Hello BA1L")), + + new State_Vafmt_PreHandler_Called(2, std::string("Hello BA1LOPAN")), + new State_Vafmt_Called(2, std::string("Hello BA1LOPAN")), + new State_Vafmt_PostHandler_Called(2, std::string("Hello BA1LOPAN")), + NULL), "Part 3"); + + // Part 4 + SH_REMOVE_HOOK(IGaben, Vafmt1, pGab, Vafmt1_PreHandler, false); + SH_REMOVE_HOOK(IGaben, Vafmt1, pGab, Vafmt1_PostHandler, true); + SH_REMOVE_HOOK(IGaben, Vafmt2, pGab, Vafmt2_PreHandler, false); + SH_REMOVE_HOOK(IGaben, Vafmt2, pGab, Vafmt2_PostHandler, true); + + pGab->Vafmt1(true, 55, "Hello %s%d%s", "BA", 1, "L"); + pGab->Vafmt2("Hello %s%d%s", "BA", 1, "LOPAN"); + + CHECK_STATES((&g_States, + new State_Vafmt_Called(1, "Hello BA1L"), + new State_Vafmt_Called(2, "Hello BA1LOPAN"), + NULL), "Part 4"); + + return true; +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/test3.cpp b/utils/mmsource/core-legacy/sourcehook/test/test3.cpp new file mode 100644 index 00000000..f78d61c9 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/test3.cpp @@ -0,0 +1,232 @@ +#include +#include "sourcehook_test.h" +#include "testevents.h" + +// TEST3 +// Tests with inheritance / thisptroffsets + +namespace +{ + StateList g_States; + SourceHook::ISourceHook *g_SHPtr; + SourceHook::Plugin g_PLID; + + MAKE_STATE_1(State_Func1_Called, void*); // param1: This pointer + MAKE_STATE_1(State_Func2_Called, void*); // param1: This pointer + MAKE_STATE_1(State_Func3_Called, void*); // param1: This pointer + + MAKE_STATE_1(State_Func1H_Called, void*); + MAKE_STATE_1(State_Func2H_Called, void*); + MAKE_STATE_1(State_Func3H_Called, void*); + + class Base1 + { + int a; + public: + virtual void Func1() + { + ADD_STATE(State_Func1_Called(reinterpret_cast(this))); + } + }; + class Base2 + { + int b; + public: + virtual void Func2() + { + ADD_STATE(State_Func2_Called(reinterpret_cast(this))); + } + }; + class Derived : public Base1, public Base2 + { + int c; + public: + virtual void Func3() + { + ADD_STATE(State_Func3_Called(reinterpret_cast(this))); + } + }; + + class DerivedDerived : public Derived { }; + + SH_DECL_HOOK0_void(Derived, Func1, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Derived, Func2, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Derived, Func3, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Base1, Func1, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Base2, Func2, SH_NOATTRIB, 0); + + void Handler_Func1() + { + ADD_STATE(State_Func1H_Called(META_IFACEPTR(void))); + } + void Handler_Func2() + { + ADD_STATE(State_Func2H_Called(META_IFACEPTR(void))); + } + void Handler_Func3() + { + ADD_STATE(State_Func3H_Called(META_IFACEPTR(void))); + } +} + +bool TestThisPtrOffs(std::string &error) +{ + GET_SHPTR(g_SHPtr); + g_PLID = 1337; + + DerivedDerived inst; + Derived *pD = &inst; + Base1 *pB1 = pD; + Base2 *pB2 = pD; + + // It should be: + // pB1 = pD + // pB2 > pB1 + + // 1) + // Get a callclass for pD + // Verify whether the this pointers are correct + // Also call them normally to make sure that we aren't messing it up ;) + + SH_CALL(pD, &Derived::Func1)(); + SH_CALL(pD, &Derived::Func2)(); + SH_CALL(pD, &Derived::Func3)(); + pD->Func1(); + pD->Func2(); + pD->Func3(); + + CHECK_STATES((&g_States, + new State_Func1_Called(pB1), + new State_Func2_Called(pB2), + new State_Func3_Called(pD), + new State_Func1_Called(pB1), + new State_Func2_Called(pB2), + new State_Func3_Called(pD), + NULL), "Part 1"); + + SH_CALL(pD, &Base1::Func1)(); + SH_CALL(pD, &Base2::Func2)(); + + CHECK_STATES((&g_States, + new State_Func1_Called(pB1), + new State_Func2_Called(pB2), + NULL), "Part 1.1"); + + // 2) + // Get callclasses for the other ones and verify it as well + + SH_CALL(pB1, &Base1::Func1)(); + SH_CALL(pB2, &Base2::Func2)(); + + CHECK_STATES((&g_States, + new State_Func1_Called(pB1), + new State_Func2_Called(pB2), + NULL), "Part 2"); + + + // 3) Add hooks on them (referring to them through pD1 / Derived) + // Check whether the hooks are called with the correct this pointer + + SH_ADD_HOOK(Derived, Func1, pD, SH_STATIC(Handler_Func1), false); + SH_ADD_HOOK(Derived, Func2, pD, SH_STATIC(Handler_Func2), false); + SH_ADD_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false); + + pD->Func1(); + pD->Func2(); + pD->Func3(); + pB1->Func1(); + pB2->Func2(); + + // The handlers should always be called with the pointer to Derived + CHECK_STATES((&g_States, + new State_Func1H_Called(pD), + new State_Func1_Called(pB1), + new State_Func2H_Called(pD), + new State_Func2_Called(pB2), + new State_Func3H_Called(pD), + new State_Func3_Called(pD), + new State_Func1H_Called(pD), + new State_Func1_Called(pB1), + new State_Func2H_Called(pD), + new State_Func2_Called(pB2), + NULL), "Part 3"); + + SH_REMOVE_HOOK(Derived, Func1, pD, SH_STATIC(Handler_Func1), false); + SH_REMOVE_HOOK(Derived, Func2, pD, SH_STATIC(Handler_Func2), false); + SH_REMOVE_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false); + + // 4) + // Now add the hooks on Base1 and Base2 and check again + + // Note that the new implicit_cast should convert the pD to Base1*/Base2* :) + SH_ADD_HOOK(Base1, Func1, pD, SH_STATIC(Handler_Func1), false); + SH_ADD_HOOK(Base2, Func2, pD, SH_STATIC(Handler_Func2), false); + SH_ADD_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false); + + pD->Func1(); + pD->Func2(); + pD->Func3(); + pB1->Func1(); + pB2->Func2(); + + // This time, the handlers for Func1 should be called with pB1 and the handlers + // for Func2 should be called with pB2 + CHECK_STATES((&g_States, + new State_Func1H_Called(pB1), + new State_Func1_Called(pB1), + new State_Func2H_Called(pB2), + new State_Func2_Called(pB2), + new State_Func3H_Called(pD), + new State_Func3_Called(pD), + new State_Func1H_Called(pB1), + new State_Func1_Called(pB1), + new State_Func2H_Called(pB2), + new State_Func2_Called(pB2), + NULL), "Part 4"); + + SH_REMOVE_HOOK(Base1, Func1, pD, SH_STATIC(Handler_Func1), false); + SH_REMOVE_HOOK(Base2, Func2, pD, SH_STATIC(Handler_Func2), false); + SH_REMOVE_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false); + + + // 5) + // Add some hooks, and use callclasses + + // 5.1) First off, add all of them on pD + SH_ADD_HOOK(Derived, Func1, pD, SH_STATIC(Handler_Func1), false); + SH_ADD_HOOK(Derived, Func2, pD, SH_STATIC(Handler_Func2), false); + SH_ADD_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false); + + pD->Func1(); + pD->Func2(); + pD->Func3(); + + CHECK_STATES((&g_States, + new State_Func1H_Called(pD), + new State_Func1_Called(pB1), + new State_Func2H_Called(pD), + new State_Func2_Called(pB2), + new State_Func3H_Called(pD), + new State_Func3_Called(pD), + NULL), "Part 5.1"); + + SH_CALL(pD, &Derived::Func1)(); + SH_CALL(pD, &Derived::Func2)(); + SH_CALL(pD, &Derived::Func3)(); + SH_CALL(pB1, &Base1::Func1)(); + SH_CALL(pB2, &Base2::Func2)(); + + CHECK_STATES((&g_States, + new State_Func1_Called(pB1), + new State_Func2_Called(pB2), + new State_Func3_Called(pD), + new State_Func1_Called(pB1), + new State_Func2_Called(pB2), + NULL), "Part 5.2"); + + SH_REMOVE_HOOK(Derived, Func1, pD, SH_STATIC(Handler_Func1), false); + SH_REMOVE_HOOK(Derived, Func2, pD, SH_STATIC(Handler_Func2), false); + SH_REMOVE_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false); + + return true; +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/test4.cpp b/utils/mmsource/core-legacy/sourcehook/test/test4.cpp new file mode 100644 index 00000000..483cab52 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/test4.cpp @@ -0,0 +1,425 @@ +#include +#include "sourcehook_test.h" +#include "testevents.h" + +// TEST4 +// Tests of plugin management system + +namespace +{ + StateList g_States; + SourceHook::ISourceHook *g_SHPtr; + SourceHook::Plugin g_PLID; + + MAKE_STATE(State_Func1_Called); + MAKE_STATE(State_Func2_Called); + MAKE_STATE(State_Func3_Called); + + MAKE_STATE(State_Func1H_Called); + MAKE_STATE(State_Func2H_Called); + MAKE_STATE(State_Func3H_Called); + + MAKE_STATE_2(State_PluginInUse, int, bool); + + class Test + { + public: + virtual void Func1() + { + ADD_STATE(State_Func1_Called); + } + + virtual void Func2() + { + ADD_STATE(State_Func2_Called); + } + + virtual void Func3() + { + ADD_STATE(State_Func3_Called); + } + }; + + // GCC's optimizer is too good. I had to add this in order to make it execute a virtual table lookup! + class Whatever : public Test + { + }; + + SH_DECL_HOOK0_void(Test, Func1, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Test, Func2, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(Test, Func3, SH_NOATTRIB, 0); + + void Handler_Func1() + { + ADD_STATE(State_Func1H_Called); + } + void Handler_Func2() + { + ADD_STATE(State_Func2H_Called); + } + void Handler_Func3() + { + ADD_STATE(State_Func3H_Called); + } +} + +bool TestPlugSys(std::string &error) +{ + GET_SHPTR(g_SHPtr); + g_PLID = 1; + + Whatever inst; + Test *pInst = &inst; + + // 1) + // Add hooks, then issue a complete shutdown + SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); + SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); + SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); + + pInst->Func1(); + pInst->Func2(); + pInst->Func3(); + + CHECK_STATES((&g_States, + new State_Func1H_Called, + new State_Func1_Called, + new State_Func2_Called, + new State_Func2H_Called, + new State_Func3H_Called, + new State_Func3_Called, + NULL), "Part 1.1"); + + Test_CompleteShutdown(g_SHPtr); + + pInst->Func1(); + pInst->Func2(); + pInst->Func3(); + + CHECK_STATES((&g_States, + new State_Func1_Called, + new State_Func2_Called, + new State_Func3_Called, + NULL), "Part 1.2"); + + // 2) + // Add hooks from "different plugins", then shutdown the plugins + + g_PLID = 1; + SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); + g_PLID = 2; + SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); + g_PLID = 3; + SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); + + g_PLID = 1; + SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); + SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); + + g_PLID = 2; + SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); + SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); + + g_PLID = 3; + SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); + SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); + + pInst->Func1(); + pInst->Func2(); + pInst->Func3(); + + CHECK_STATES((&g_States, + new State_Func1H_Called, + new State_Func1H_Called, + new State_Func1H_Called, + new State_Func1_Called, + new State_Func2_Called, + new State_Func2H_Called, + new State_Func2H_Called, + new State_Func2H_Called, + new State_Func3H_Called, + new State_Func3H_Called, + new State_Func3H_Called, + new State_Func3_Called, + NULL), "Part 2.1"); + + ADD_STATE(State_PluginInUse(1, Test_IsPluginInUse(g_SHPtr, 1))); + ADD_STATE(State_PluginInUse(2, Test_IsPluginInUse(g_SHPtr, 2))); + ADD_STATE(State_PluginInUse(3, Test_IsPluginInUse(g_SHPtr, 3))); + ADD_STATE(State_PluginInUse(4, Test_IsPluginInUse(g_SHPtr, 4))); + + CHECK_STATES((&g_States, + new State_PluginInUse(1, true), + new State_PluginInUse(2, true), + new State_PluginInUse(3, true), + new State_PluginInUse(4, false), + NULL), "Part 2.2"); + + // Unload plugins one by one + Test_UnloadPlugin(g_SHPtr, 3); + + pInst->Func1(); + pInst->Func2(); + pInst->Func3(); + + CHECK_STATES((&g_States, + new State_Func1H_Called, + new State_Func1H_Called, + new State_Func1_Called, + new State_Func2_Called, + new State_Func2H_Called, + new State_Func2H_Called, + new State_Func3H_Called, + new State_Func3H_Called, + new State_Func3_Called, + NULL), "Part 2.3.1"); + + ADD_STATE(State_PluginInUse(1, Test_IsPluginInUse(g_SHPtr, 1))); + ADD_STATE(State_PluginInUse(2, Test_IsPluginInUse(g_SHPtr, 2))); + ADD_STATE(State_PluginInUse(3, Test_IsPluginInUse(g_SHPtr, 3))); + ADD_STATE(State_PluginInUse(4, Test_IsPluginInUse(g_SHPtr, 4))); + + CHECK_STATES((&g_States, + new State_PluginInUse(1, true), + new State_PluginInUse(2, true), + new State_PluginInUse(3, false), + new State_PluginInUse(4, false), + NULL), "Part 2.3.2"); + + Test_UnloadPlugin(g_SHPtr, 2); + + pInst->Func1(); + pInst->Func2(); + pInst->Func3(); + + CHECK_STATES((&g_States, + new State_Func1H_Called, + new State_Func1_Called, + new State_Func2_Called, + new State_Func2H_Called, + new State_Func3H_Called, + new State_Func3_Called, + NULL), "Part 2.4.1"); + + ADD_STATE(State_PluginInUse(1, Test_IsPluginInUse(g_SHPtr, 1))); + ADD_STATE(State_PluginInUse(2, Test_IsPluginInUse(g_SHPtr, 2))); + ADD_STATE(State_PluginInUse(3, Test_IsPluginInUse(g_SHPtr, 3))); + ADD_STATE(State_PluginInUse(4, Test_IsPluginInUse(g_SHPtr, 4))); + + CHECK_STATES((&g_States, + new State_PluginInUse(1, true), + new State_PluginInUse(2, false), + new State_PluginInUse(3, false), + new State_PluginInUse(4, false), + NULL), "Part 2.4.2"); + + Test_UnloadPlugin(g_SHPtr, 1); + + pInst->Func1(); + pInst->Func2(); + pInst->Func3(); + + CHECK_STATES((&g_States, + new State_Func1_Called, + new State_Func2_Called, + new State_Func3_Called, + NULL), "Part 2.5.1"); + + ADD_STATE(State_PluginInUse(1, Test_IsPluginInUse(g_SHPtr, 1))); + ADD_STATE(State_PluginInUse(2, Test_IsPluginInUse(g_SHPtr, 2))); + ADD_STATE(State_PluginInUse(3, Test_IsPluginInUse(g_SHPtr, 3))); + ADD_STATE(State_PluginInUse(4, Test_IsPluginInUse(g_SHPtr, 4))); + + CHECK_STATES((&g_States, + new State_PluginInUse(1, false), + new State_PluginInUse(2, false), + new State_PluginInUse(3, false), + new State_PluginInUse(4, false), + NULL), "Part 2.5.2"); + + + // 3) + // Add hooks from "different plugins", then pause the plugins + + g_PLID = 1; + SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); + g_PLID = 2; + SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); + g_PLID = 3; + SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); + + g_PLID = 1; + SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); + SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); + + g_PLID = 2; + SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); + SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); + + g_PLID = 3; + SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); + SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); + + pInst->Func1(); + pInst->Func2(); + pInst->Func3(); + + CHECK_STATES((&g_States, + new State_Func1H_Called, + new State_Func1H_Called, + new State_Func1H_Called, + new State_Func1_Called, + new State_Func2_Called, + new State_Func2H_Called, + new State_Func2H_Called, + new State_Func2H_Called, + new State_Func3H_Called, + new State_Func3H_Called, + new State_Func3H_Called, + new State_Func3_Called, + NULL), "Part 3.1"); + + ADD_STATE(State_PluginInUse(1, Test_IsPluginInUse(g_SHPtr, 1))); + ADD_STATE(State_PluginInUse(2, Test_IsPluginInUse(g_SHPtr, 2))); + ADD_STATE(State_PluginInUse(3, Test_IsPluginInUse(g_SHPtr, 3))); + ADD_STATE(State_PluginInUse(4, Test_IsPluginInUse(g_SHPtr, 4))); + + CHECK_STATES((&g_States, + new State_PluginInUse(1, true), + new State_PluginInUse(2, true), + new State_PluginInUse(3, true), + new State_PluginInUse(4, false), + NULL), "Part 3.2"); + + // Unload plugins one by one + Test_PausePlugin(g_SHPtr, 3); + + pInst->Func1(); + pInst->Func2(); + pInst->Func3(); + + CHECK_STATES((&g_States, + new State_Func1H_Called, + new State_Func1H_Called, + new State_Func1_Called, + new State_Func2_Called, + new State_Func2H_Called, + new State_Func2H_Called, + new State_Func3H_Called, + new State_Func3H_Called, + new State_Func3_Called, + NULL), "Part 3.3.1"); + + ADD_STATE(State_PluginInUse(1, Test_IsPluginInUse(g_SHPtr, 1))); + ADD_STATE(State_PluginInUse(2, Test_IsPluginInUse(g_SHPtr, 2))); + ADD_STATE(State_PluginInUse(3, Test_IsPluginInUse(g_SHPtr, 3))); + ADD_STATE(State_PluginInUse(4, Test_IsPluginInUse(g_SHPtr, 4))); + + CHECK_STATES((&g_States, + new State_PluginInUse(1, true), + new State_PluginInUse(2, true), + new State_PluginInUse(3, true), + new State_PluginInUse(4, false), + NULL), "Part 3.3.2"); + + Test_PausePlugin(g_SHPtr, 2); + + pInst->Func1(); + pInst->Func2(); + pInst->Func3(); + + CHECK_STATES((&g_States, + new State_Func1H_Called, + new State_Func1_Called, + new State_Func2_Called, + new State_Func2H_Called, + new State_Func3H_Called, + new State_Func3_Called, + NULL), "Part 3.4.1"); + + ADD_STATE(State_PluginInUse(1, Test_IsPluginInUse(g_SHPtr, 1))); + ADD_STATE(State_PluginInUse(2, Test_IsPluginInUse(g_SHPtr, 2))); + ADD_STATE(State_PluginInUse(3, Test_IsPluginInUse(g_SHPtr, 3))); + ADD_STATE(State_PluginInUse(4, Test_IsPluginInUse(g_SHPtr, 4))); + + CHECK_STATES((&g_States, + new State_PluginInUse(1, true), + new State_PluginInUse(2, true), + new State_PluginInUse(3, true), + new State_PluginInUse(4, false), + NULL), "Part 3.4.2"); + + Test_PausePlugin(g_SHPtr, 1); + + pInst->Func1(); + pInst->Func2(); + pInst->Func3(); + + CHECK_STATES((&g_States, + new State_Func1_Called, + new State_Func2_Called, + new State_Func3_Called, + NULL), "Part 3.5.1"); + + ADD_STATE(State_PluginInUse(1, Test_IsPluginInUse(g_SHPtr, 1))); + ADD_STATE(State_PluginInUse(2, Test_IsPluginInUse(g_SHPtr, 2))); + ADD_STATE(State_PluginInUse(3, Test_IsPluginInUse(g_SHPtr, 3))); + ADD_STATE(State_PluginInUse(4, Test_IsPluginInUse(g_SHPtr, 4))); + + CHECK_STATES((&g_States, + new State_PluginInUse(1, true), + new State_PluginInUse(2, true), + new State_PluginInUse(3, true), + new State_PluginInUse(4, false), + NULL), "Part 3.5.2"); + + Test_UnpausePlugin(g_SHPtr, 1); + Test_UnpausePlugin(g_SHPtr, 2); + Test_UnpausePlugin(g_SHPtr, 3); + + ADD_STATE(State_PluginInUse(1, Test_IsPluginInUse(g_SHPtr, 1))); + ADD_STATE(State_PluginInUse(2, Test_IsPluginInUse(g_SHPtr, 2))); + ADD_STATE(State_PluginInUse(3, Test_IsPluginInUse(g_SHPtr, 3))); + ADD_STATE(State_PluginInUse(4, Test_IsPluginInUse(g_SHPtr, 4))); + + CHECK_STATES((&g_States, + new State_PluginInUse(1, true), + new State_PluginInUse(2, true), + new State_PluginInUse(3, true), + new State_PluginInUse(4, false), + NULL), "Part 3.6"); + + pInst->Func1(); + pInst->Func2(); + pInst->Func3(); + + CHECK_STATES((&g_States, + new State_Func1H_Called, + new State_Func1H_Called, + new State_Func1H_Called, + new State_Func1_Called, + new State_Func2_Called, + new State_Func2H_Called, + new State_Func2H_Called, + new State_Func2H_Called, + new State_Func3H_Called, + new State_Func3H_Called, + new State_Func3H_Called, + new State_Func3_Called, + NULL), "Part 3.7"); + + // 4) Shutdown :) + Test_CompleteShutdown(g_SHPtr); + + pInst->Func1(); + pInst->Func2(); + pInst->Func3(); + + CHECK_STATES((&g_States, + new State_Func1_Called, + new State_Func2_Called, + new State_Func3_Called, + NULL), "Part 4"); + + return true; +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/testbail.cpp b/utils/mmsource/core-legacy/sourcehook/test/testbail.cpp new file mode 100644 index 00000000..46f7b9d3 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/testbail.cpp @@ -0,0 +1,115 @@ +// TESTBAIL +// This test used to be a test for a bug BAIL found. +// That bug is now fixed so I've granted BAIL the pleasure of being a test for +// the correct priority ordering of hook managers based on their version. + +/* + THE PROBLEM: + Old hook funcs don't work right when you combine override returns and recalls. + THE SOLUTION: + Always use a new hook func when possible. For this, hook funcs have to be able to say + " HELLO I'M NEW! " + + This file tests that functionality. + + How it works: + testbail.cpp compiles with old version of sourcehook.h. + It sets everything up, adds a hook on a function + Then testbail2.cpp which has the new version adds a hook on the same function and + does a recall and overrides the value in it. +*/ +#include "sourcehook_test.h" +#include "testbail.h" + +namespace N_TestBail +{ + StateList g_States; + SourceHook::ISourceHook *g_SHPtr; + IGaben *g_Gabgab; +} + +namespace +{ + int EatYams_Handler1(int a) + { + ADD_STATE(State_EatYams_Handler1_Called(a)); + RETURN_META_VALUE(MRES_IGNORED, 0); + } +} + +bool TestBail(std::string &error) +{ + GET_SHPTR(g_SHPtr); + g_PLID = 1; + + g_Gabgab = new IGaben; + + SH_ADD_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler1), false); + + ADD_STATE(State_EatYams_Return(g_Gabgab->EatYams(0xDEAD))); + + CHECK_STATES((&g_States, + new State_EatYams_Handler1_Called(0xDEAD), + new State_EatYams_Called(0xDEAD), + new State_EatYams_Return(5), + NULL), "Part 1"); + + if (!TestBail2(error)) + return false; + + CHECK_STATES((&g_States, + new State_EatYams_Handler1_Called(0xDEAD), + new State_EatYams_Handler2_Called(0xDEAD), + new State_EatYams_Handler3_Called(0xBEEF), + new State_EatYams_Called(0xBEEF), + NULL), "Part 2.1"); + + // WHAT IF NOW SOMEONE UNLOADS PLUGIN 2 !?!?!?!? + Test_UnloadPlugin(g_SHPtr, 2); + + ADD_STATE(State_EatYams_Return(g_Gabgab->EatYams(0xDEAD))); + + CHECK_STATES((&g_States, + new State_EatYams_Handler1_Called(0xDEAD), + new State_EatYams_Called(0xDEAD), + new State_EatYams_Return(5), + NULL), "Part 3"); + + SH_REMOVE_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler1), false); + + ADD_STATE(State_EatYams_Return(g_Gabgab->EatYams(0xDEAD))); + + CHECK_STATES((&g_States, + new State_EatYams_Called(0xDEAD), + new State_EatYams_Return(5), + NULL), "Part 4"); + + // Now, heh, try it the other way round. + + Test_CompleteShutdown(g_SHPtr); + + if (!TestBail2(error)) + return false; + + CHECK_STATES((&g_States, + new State_EatYams_Handler2_Called(0xDEAD), + new State_EatYams_Handler3_Called(0xBEEF), + new State_EatYams_Called(0xBEEF), + NULL), "Part 5"); + + SH_ADD_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler1), false); + + ADD_STATE(State_EatYams_Return(g_Gabgab->EatYams(0xDEAD))); + + CHECK_STATES((&g_States, + new State_EatYams_Handler2_Called(0xDEAD), + new State_EatYams_Handler3_Called(0xBEEF), + new State_EatYams_Handler1_Called(0xBEEF), + new State_EatYams_Called(0xBEEF), + new State_EatYams_Return(6), + NULL), "Part 6"); + + delete g_Gabgab; + + return true; +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/testbail.h b/utils/mmsource/core-legacy/sourcehook/test/testbail.h new file mode 100644 index 00000000..258a49c3 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/testbail.h @@ -0,0 +1,39 @@ +////////////////////////////////////////////////////////////////////////// +// Shared data for testbail + +#include +#include "testevents.h" + +namespace N_TestBail +{ + extern StateList g_States; + extern SourceHook::ISourceHook *g_SHPtr; + + MAKE_STATE_1(State_EatYams_Called, int); + MAKE_STATE_1(State_EatYams_Handler1_Called, int); + MAKE_STATE_1(State_EatYams_Handler2_Called, int); + MAKE_STATE_1(State_EatYams_Handler3_Called, int); + MAKE_STATE_1(State_EatYams_Return, int); + + class IGaben + { + public: + virtual int EatYams(int a) + { + ADD_STATE(State_EatYams_Called(a)); + return 5; + } + }; + + extern IGaben *g_Gabgab; + + bool TestBail2(std::string &error); +} + +using namespace N_TestBail; + +namespace +{ + SourceHook::Plugin g_PLID; + SH_DECL_HOOK1(IGaben, EatYams, SH_NOATTRIB, 0, int, int); +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/testbail2.cpp b/utils/mmsource/core-legacy/sourcehook/test/testbail2.cpp new file mode 100644 index 00000000..d3f7f28a --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/testbail2.cpp @@ -0,0 +1,36 @@ +// TESTBAIL +// Different compilation unit + +#include "sourcehook.h" +#include "sourcehook_test.h" +#include "testbail.h" + + +int EatYams_Handler2(int a) +{ + ADD_STATE(State_EatYams_Handler2_Called(a)); + RETURN_META_VALUE_NEWPARAMS(MRES_OVERRIDE, 6, &IGaben::EatYams, (0xBEEF)); +} + +int EatYams_Handler3(int a) +{ + ADD_STATE(State_EatYams_Handler3_Called(a)); + RETURN_META_VALUE(MRES_IGNORED, 0); +} + +namespace N_TestBail +{ + bool TestBail2(std::string &error) + { + g_PLID = 2; + + SH_ADD_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler2), false); + SH_ADD_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler3), false); + + int ret = g_Gabgab->EatYams(0xDEAD); + + CHECK_COND(ret == 6, "Part 2.1"); + + return true; + } +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/testevents.h b/utils/mmsource/core-legacy/sourcehook/test/testevents.h new file mode 100644 index 00000000..9123469c --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/testevents.h @@ -0,0 +1,161 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2007 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +#ifndef __TESTEVENTS_H__ +#define __TESTEVENTS_H__ + +#include +#include +#include +#include +#include + +extern bool g_Verbose; + +struct State +{ + virtual ~State() + { + + } + + virtual bool IsEqual(State *other) + { + return (typeid(other) == typeid(this)) ? true : false; + } + + virtual void Dump() = 0; +}; + +typedef std::list StateList; +namespace +{ + void DumpStates(StateList *sl) + { + for (StateList::iterator iter = sl->begin(); iter != sl->end(); ++iter) + (*iter)->Dump(); + } + + bool StatesOk(StateList *sl, ...) + { + StateList requiredstates; + va_list argptr; + va_start(argptr, sl); + while (true) + { + State *cs = va_arg(argptr, State*); + if (!cs) + break; + requiredstates.push_back(cs); + } + va_end(argptr); + + if (requiredstates.size() != sl->size()) + { + if (g_Verbose) + { + std::cout << std::endl << "FAIL: Should be:" << std::endl; + DumpStates(&requiredstates); + std::cout << std::endl << "FAIL: Is:" << std::endl; + DumpStates(sl); + } + + for (StateList::iterator iter = requiredstates.begin(); iter != requiredstates.end(); ++iter) + delete *iter; + for (StateList::iterator iter = sl->begin(); iter != sl->end(); ++iter) + delete *iter; + sl->clear(); + return false; + } + + bool ok = true; + StateList::iterator req_iter = requiredstates.begin(); + for (StateList::iterator o_iter = sl->begin(); o_iter != sl->end(); ++o_iter, ++req_iter) + { + if (!(*o_iter)->IsEqual(*req_iter)) + { + ok = false; + break; + } + } + + if (!ok && g_Verbose) + { + std::cout << std::endl << "FAIL: Should be:" << std::endl; + DumpStates(&requiredstates); + std::cout << std::endl << "FAIL: Is:" << std::endl; + DumpStates(sl); + } + + for (StateList::iterator iter = requiredstates.begin(); iter != requiredstates.end(); ++iter) + delete *iter; + for (StateList::iterator iter = sl->begin(); iter != sl->end(); ++iter) + delete *iter; + sl->clear(); + + return ok; + } +} + +#define ADD_STATE(name) g_States.push_back(new name) +#define ADD_STATE_PTR(statesptr, name) statesptr->push_back(new name) + +#define CHECK_STATES(mwah, myerr) if (!StatesOk mwah) { error=myerr; return false; } else if (g_Verbose) { std::cout << "No error: " << myerr << std::endl; } + +#define MAKE_STATE(name) struct name : State { \ + virtual void Dump() { \ + std::cout << " " << #name << std::endl; } \ + }; + +#define MAKE_STATE_1(name, p1_type) struct name : State { \ + p1_type m_Param1; \ + name(p1_type param1) : m_Param1(param1) {} \ + virtual bool IsEqual(State *other) { \ + name *other2 = dynamic_cast(other); \ + if (!other2) \ + return false; \ + return other2->m_Param1 == m_Param1;\ + } \ + virtual void Dump() { \ + std::cout << " " << #name << "; Param1=" << m_Param1 << std::endl; } \ + } + +#define MAKE_STATE_2(name, p1_type, p2_type) struct name : State { \ + p1_type m_Param1; \ + p2_type m_Param2; \ + name(p1_type param1, p2_type param2) : m_Param1(param1), m_Param2(param2) {} \ + virtual bool IsEqual(State *other) { \ + name *other2 = dynamic_cast(other); \ + if (!other2) \ + return false; \ + return other2->m_Param1 == m_Param1 && other2->m_Param2 == m_Param2;\ + } \ + virtual void Dump() { \ + std::cout << " " << #name << "; Param1=" << m_Param1 << "; Param2=" << m_Param2 << std::endl; } \ + } + +#define MAKE_STATE_3(name, p1_type, p2_type, p3_type) struct name : State { \ + p1_type m_Param1; \ + p2_type m_Param2; \ + p3_type m_Param3; \ + name(p1_type param1, p2_type param2, p3_type param3) : m_Param1(param1), m_Param2(param2), m_Param3(param3) {} \ + virtual bool IsEqual(State *other) { \ + name *other2 = dynamic_cast(other); \ + if (!other2) \ + return false; \ + return other2->m_Param1 == m_Param1 && other2->m_Param2 == m_Param2 && other2->m_Param3 == m_Param3;\ + } \ + virtual void Dump() { \ + std::cout << " " << #name << "; Param1=" << m_Param1 << "; Param2=" << m_Param2 << "; Param3=" << m_Param3 << std::endl; } \ + } + +#define CHECK_COND(c, err) if (!(c)) { error = err; return false; } + +#endif diff --git a/utils/mmsource/core-legacy/sourcehook/test/testlist.cpp b/utils/mmsource/core-legacy/sourcehook/test/testlist.cpp new file mode 100644 index 00000000..bbaa4d31 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/testlist.cpp @@ -0,0 +1,282 @@ +#include +#include "sh_list.h" +#include "sh_stack.h" +#include "sh_tinyhash.h" +#include "sh_vector.h" +#include "testevents.h" + +// TEST LIST +// Tests sh_list, sh_tinyhash, sh_vector + +// :TODO: vector test, list insert test + +namespace +{ + struct Hmm + { + Hmm *m_This; + int m_Int; + Hmm(const Hmm &other) : m_Int(other.m_Int) + { + m_This = this; + } + Hmm(int i) : m_Int(i) + { + m_This = this; + } + Hmm() : m_Int(0) + { + m_This = this; + } + void operator = (const Hmm &other) + { + m_Int = other.m_Int; + } + operator int () const + { + return m_Int; + } + }; + + #define LIST_THIS_CHECK(lst, err) \ + for (ListType::iterator iter = lst.begin(); iter != lst.end(); ++iter) \ + CHECK_COND(&(*iter) == iter->m_This, err); + + bool DoTestList(std::string &error) + { + typedef SourceHook::List ListType; + ListType lst; + + CHECK_COND(lst.empty(), "Part1"); + + for (int i = 1; i <= 100; ++i) + lst.push_back(i); + + LIST_THIS_CHECK(lst, "PartA1"); + + CHECK_COND(!lst.empty(), "Part2"); + + lst.clear(); + + CHECK_COND(lst.empty(), "Part3"); + + for (int i = 1; i <= 100; ++i) + lst.push_back(i); + + CHECK_COND(lst.back() == 100, "Part4"); + LIST_THIS_CHECK(lst, "PartA2"); + + int ver = 1; + for (ListType::iterator iter = lst.begin(); iter != lst.end(); ++iter) + CHECK_COND(*iter == ver++, "Part5"); + + CHECK_COND(ver == 101, "Part 6"); + + ListType::iterator iter50 = lst.find(50); + CHECK_COND(*iter50 == 50, "Part7"); + + iter50 = lst.erase(iter50); + CHECK_COND(*iter50 == 51, "Part8"); + CHECK_COND(*--iter50 == 49, "Part8.2"); + + lst.remove(80); + + ver = 1; + for (ListType::iterator iter = lst.begin(); iter != lst.end(); ++iter) + { + CHECK_COND(*iter == ver++, "Part9"); + if (ver == 50 || ver == 80) + ++ver; + } + CHECK_COND(ver == 101, "Part10"); + LIST_THIS_CHECK(lst, "PartA3"); + + ListType lst2; + lst = lst2; + CHECK_COND(lst.empty(), "Part11"); + + for (int i = 1; i <= 100; ++i) + lst.push_back(i); + lst2 = lst; + CHECK_COND(lst2.size() == 100, "Part11.2"); + + LIST_THIS_CHECK(lst, "PartA4"); + LIST_THIS_CHECK(lst2, "PartA5"); + + ver = 1; + for (ListType::iterator iter = lst2.begin(); iter != lst2.end(); ++iter) + CHECK_COND(*iter == ver++, "Part12"); + + lst.clear(); + for (int i = 401; i <= 500; ++i) + lst.push_back(i); + lst = lst2; + CHECK_COND(lst2.size() == 100, "Part13"); + + ver = 1; + for (ListType::iterator iter = lst.begin(); iter != lst.end(); ++iter) + CHECK_COND(*iter == ver++, "Part14"); + + LIST_THIS_CHECK(lst, "PartA6"); + LIST_THIS_CHECK(lst2, "PartA7"); + + return true; + } + + bool DoTestTinyHash(std::string &error) + { + const int mymax = 5000; + + typedef SourceHook::THash HashType; + HashType hash; + + for (int i = 1; i <= mymax; ++i) + hash[i] = i + 5000; + + for (int i = 1; i <= mymax; ++i) + CHECK_COND(hash[i] == i + 5000, "Part1"); + + // Find + int ver = 1; + HashType::iterator iter; + for (iter = hash.begin(); iter != hash.end(); ++iter) + CHECK_COND(iter->key == ver && iter->val == (ver++) + 5000, "Part2"); + + CHECK_COND(ver == mymax+1, "Part2.1"); + + iter = hash.find(300); + CHECK_COND(iter != hash.end() && iter->val == 300+5000, "Part3.1"); + iter = hash.find(mymax+200); + CHECK_COND(iter == hash.end(), "Part3.2"); + + HashType hash2; + for (int i = 1; i <= mymax; ++i) + hash2[i] = i + 5000; + + hash2.erase(mymax - 100); + CHECK_COND(hash2.find(mymax - 101) != hash2.end(), "Part 4.1"); + CHECK_COND(hash2.find(mymax - 99) != hash2.end(), "Part 4.2"); + CHECK_COND(hash2.find(mymax - 100) == hash2.end(), "Part 4.3"); + hash2.erase(mymax - 99); + CHECK_COND(hash2.find(mymax - 101) != hash2.end(), "Part 4.4"); + CHECK_COND(hash2.find(mymax - 99) == hash2.end(), "Part 4.5"); + CHECK_COND(hash2.find(mymax - 100) == hash2.end(), "Part 4.6"); + + return true; + } + + bool DoTestStack(std::string &error) + { + typedef SourceHook::CStack IntStack; + IntStack stk; + int i; + + CHECK_COND(stk.size() == 0 && stk.empty(), "A0"); + + for (i = 0; i < 5000; ++i) + stk.push(i); + + CHECK_COND(stk.front() == 4999, "1"); + CHECK_COND(stk.size() == 5000 && !stk.empty(), "A1"); + + IntStack::iterator iter; + i = 0; + for (iter = stk.begin(); iter != stk.end(); ++iter, ++i) + CHECK_COND(*iter == i, "2"); + + i = 0; + for (iter = stk.begin(); iter != stk.end(); iter++, ++i) + CHECK_COND(*iter == i, "3"); + + --iter; + iter--; + *iter = 'g'+'a'+'b'+'e'+'n'; + stk.pop(); + + CHECK_COND(stk.size() == 4999 && !stk.empty(), "A2"); + CHECK_COND(stk.front() == 'g'+'a'+'b'+'e'+'n', "4"); + + IntStack stk2(stk); + CHECK_COND(stk2.size() == 4999 && !stk2.empty(), "A3"); + + IntStack::iterator iter2 = stk2.begin(); + for (iter = stk.begin(); iter != stk.end(); ++iter, iter2++) + CHECK_COND(*iter == *iter2, "5"); + + while (!stk2.empty()) + stk2.pop(); + CHECK_COND(stk2.size() == 0 && stk2.empty(), "A4"); + stk = stk2; + CHECK_COND(stk.size() == 0 && stk.empty(), "A5"); + + return true; + } + + bool DoTestVec(std::string &error) + { + typedef SourceHook::CVector IntVector; + IntVector vec1; + IntVector::iterator iter; + int i; + + CHECK_COND(vec1.size() == 0 && vec1.empty(), "V1"); + for (i = 0; i < 500; ++i) + vec1.push_back(i); + + CHECK_COND(vec1.size() == 500 && !vec1.empty(), "V2"); + + for (i = 0; i < 500; ++i) + CHECK_COND(vec1[i] == i, "V3"); + + for (i = 0, iter = vec1.begin(); iter != vec1.end(); ++iter, ++i) + CHECK_COND(*iter == i, "V4"); + + vec1.resize(1000); + for (i = 0; i < 500; ++i) + CHECK_COND(vec1[i] == i, "V5.1"); + for (i = 500; i < 1000; ++i) + CHECK_COND(vec1[i] == 0, "V5.2"); + + vec1.resize(200); + for (i = 0; i < 200; ++i) + CHECK_COND(vec1[i] == i, "V6"); + + vec1.resize(500, 0x12345678); + for (i = 0; i < 200; ++i) + CHECK_COND(vec1[i] == i, "V7.1"); + for (i = 200; i < 500; ++i) + CHECK_COND(vec1[i] == 0x12345678, "V7.2"); + + IntVector vec2(vec1); + CHECK_COND(vec2.size() == vec1.size() && vec2.empty() == vec1.empty(), "V8.0"); + for (i = 0; i < 200; ++i) + CHECK_COND(vec2[i] == i, "V8.1"); + for (i = 200; i < 500; ++i) + CHECK_COND(vec2[i] == 0x12345678, "V8.2"); + + + vec1.clear(); + CHECK_COND(vec1.size() == 0 && vec1.empty() && vec1.begin() == vec1.end(), "V9"); + vec2 = vec1; + CHECK_COND(vec2.size() == 0 && vec2.empty() && vec2.begin() == vec2.end(), "V9"); + + return true; + } +} + +bool TestList(std::string &error) +{ + if (!DoTestList(error)) + return false; + + if (!DoTestTinyHash(error)) + return false; + + if (!DoTestStack(error)) + return false; + + if (!DoTestVec(error)) + return false; + + return true; +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/testmanual.cpp b/utils/mmsource/core-legacy/sourcehook/test/testmanual.cpp new file mode 100644 index 00000000..ad89f43e --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/testmanual.cpp @@ -0,0 +1,369 @@ +#include +#include "sourcehook.h" +#include "sourcehook_test.h" +#include "testevents.h" + +// TESTMANUAL +// Test manual hooks +// :TODO: test more extensively + +namespace +{ + StateList g_States; + SourceHook::ISourceHook *g_SHPtr; + SourceHook::Plugin g_PLID; + + MAKE_STATE_1(State_Func1_Called, void*); // param1: This pointer + MAKE_STATE_2(State_Func2_Called, void*, int); // param1: This pointer; param2: parameter + MAKE_STATE_1(State_Func3_Called, void*); // param1: This pointer + MAKE_STATE_2(State_Func4_Called, void*, int); // param1: This pointer; param2: parameter + MAKE_STATE_1(State_Func5_Called, void*); // param1: This pointer + + MAKE_STATE_1(State_Func1H_Called, void*); + MAKE_STATE_2(State_Func2H_Called, void*, int); + MAKE_STATE_1(State_Func3H_Called, void*); + MAKE_STATE_2(State_Func4H_Called, void*, int); + + MAKE_STATE_1(State_Return, short); + + class TheWall + { + public: + virtual void Func1() + { + ADD_STATE(State_Func1_Called(reinterpret_cast(this))); + } + virtual void Func2(int x) + { + ADD_STATE(State_Func2_Called(reinterpret_cast(this), x)); + } + + virtual short Func3() + { + ADD_STATE(State_Func3_Called(reinterpret_cast(this))); + return 3; + } + virtual short Func4(int x) + { + ADD_STATE(State_Func4_Called(reinterpret_cast(this), x)); + return 4; + } + virtual void Func5() + { + ADD_STATE(State_Func5_Called(reinterpret_cast(this))); + } + + }; + // GCC's optimizer is too good. I had to add this in order to make it execute a virtual table lookup! + class Whatever : public TheWall + { + }; + + SH_DECL_HOOK0_void(TheWall, Func1, SH_NOATTRIB, 0); + SH_DECL_HOOK1_void(TheWall, Func2, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0(TheWall, Func3, SH_NOATTRIB, 0, short); + SH_DECL_HOOK1(TheWall, Func4, SH_NOATTRIB, 0, short, int); + + SH_DECL_MANUALHOOK0_void(TheWall_Func1, 0, 0, 0); + SH_DECL_MANUALHOOK1_void(TheWall_Func2, 1, 0, 0, int); + SH_DECL_MANUALHOOK0(TheWall_Func3, 2, 0, 0, short); + SH_DECL_MANUALHOOK1(TheWall_Func4, 3, 0, 0, short, int); + + typedef void (SourceHook::EmptyClass::*MFP_Func1)(); + typedef void (SourceHook::EmptyClass::*MFP_Func2)(int); + typedef short (SourceHook::EmptyClass::*MFP_Func3)(); + typedef short (SourceHook::EmptyClass::*MFP_Func4)(int); + + void Handler_Func1() + { + ADD_STATE(State_Func1H_Called(META_IFACEPTR(void))); + } + void Handler_Func2(int x) + { + ADD_STATE(State_Func2H_Called(META_IFACEPTR(void), x)); + RETURN_META_MNEWPARAMS(MRES_IGNORED, TheWall_Func2, (0x87654321)); + } + short Handler_Func3() + { + ADD_STATE(State_Func3H_Called(META_IFACEPTR(void))); + return 0; + } + short Handler_Func4(int x) + { + ADD_STATE(State_Func4H_Called(META_IFACEPTR(void), x)); + + // newparams (recall) using the manual hook declaration! + RETURN_META_VALUE_MNEWPARAMS(MRES_IGNORED, 0, TheWall_Func4, (0x12345678)); + } + + struct AnotherBrick + { + void Handler_Func1() + { + ADD_STATE(State_Func1H_Called(META_IFACEPTR(void))); + RETURN_META(MRES_SUPERCEDE); + } + }; +} + +bool TestManual(std::string &error) +{ + GET_SHPTR(g_SHPtr); + g_PLID = 1337; + + Whatever inst; + TheWall *p = &inst; + + // 1) + // Call each function + p->Func1(); + p->Func2(200); + ADD_STATE(State_Return(p->Func3())); + ADD_STATE(State_Return(p->Func4(400))); + + CHECK_STATES((&g_States, + new State_Func1_Called(p), + new State_Func2_Called(p, 200), + new State_Func3_Called(p), + new State_Return(3), + new State_Func4_Called(p, 400), + new State_Return(4), + NULL), "Part 1"); + + // 1.1) + // Now call each function through the manual call class, using the hook decl and manually + SH_MCALL(p, TheWall_Func1)(); + SH_MCALL2(p, MFP_Func1(), 0, 0, 0)(); + SH_MCALL(p, TheWall_Func2)(200); + SH_MCALL2(p, MFP_Func2(), 1, 0, 0)(200); + ADD_STATE(State_Return(SH_MCALL(p, TheWall_Func3)())); + ADD_STATE(State_Return(SH_MCALL2(p, MFP_Func3(), 2, 0, 0)())); + ADD_STATE(State_Return(SH_MCALL(p, TheWall_Func4)(400))); + ADD_STATE(State_Return(SH_MCALL2(p, MFP_Func4(), 3, 0, 0)(400))); + + CHECK_STATES((&g_States, + new State_Func1_Called(p), + new State_Func1_Called(p), + new State_Func2_Called(p, 200), + new State_Func2_Called(p, 200), + new State_Func3_Called(p), + new State_Return(3), + new State_Func3_Called(p), + new State_Return(3), + new State_Func4_Called(p, 400), + new State_Return(4), + new State_Func4_Called(p, 400), + new State_Return(4), + NULL), "Part 1.1"); + + // Compat: really get a manual call class! + SourceHook::ManualCallClass *pCC = SH_GET_MCALLCLASS(p, sizeof(void*)); + SH_MCALL(pCC, TheWall_Func1)(); + SH_MCALL2(pCC, MFP_Func1(), 0, 0, 0)(); + CHECK_STATES((&g_States, + new State_Func1_Called(p), + new State_Func1_Called(p), + NULL), "Part 1.2"); + + SH_RELEASE_CALLCLASS(pCC); + + // 2) + // Hook each function normally, call them + SH_ADD_HOOK(TheWall, Func1, p, SH_STATIC(Handler_Func1), false); + SH_ADD_HOOK(TheWall, Func2, p, SH_STATIC(Handler_Func2), false); + SH_ADD_HOOK(TheWall, Func3, p, SH_STATIC(Handler_Func3), false); + SH_ADD_HOOK(TheWall, Func4, p, SH_STATIC(Handler_Func4), false); + + p->Func1(); + p->Func2(200); + ADD_STATE(State_Return(p->Func3())); + ADD_STATE(State_Return(p->Func4(400))); + + CHECK_STATES((&g_States, + new State_Func1H_Called(p), + new State_Func1_Called(p), + new State_Func2H_Called(p, 200), + new State_Func2_Called(p, 0x87654321), + new State_Func3H_Called(p), + new State_Func3_Called(p), + new State_Return(3), + new State_Func4H_Called(p, 400), + new State_Func4_Called(p, 0x12345678), + new State_Return(4), + NULL), "Part 2"); + + // Call them through the mcallclass + // 2.1) + // Now call each function through the manual call class, using the hook decl and manually + SH_MCALL(p, TheWall_Func1)(); + SH_MCALL2(p, MFP_Func1(), 0, 0, 0)(); + SH_MCALL(p, TheWall_Func2)(200); + SH_MCALL2(p, MFP_Func2(), 1, 0, 0)(200); + ADD_STATE(State_Return(SH_MCALL(p, TheWall_Func3)())); + ADD_STATE(State_Return(SH_MCALL2(p, MFP_Func3(), 2, 0, 0)())); + ADD_STATE(State_Return(SH_MCALL(p, TheWall_Func4)(400))); + ADD_STATE(State_Return(SH_MCALL2(p, MFP_Func4(), 3, 0, 0)(400))); + + CHECK_STATES((&g_States, + new State_Func1_Called(p), + new State_Func1_Called(p), + new State_Func2_Called(p, 200), + new State_Func2_Called(p, 200), + new State_Func3_Called(p), + new State_Return(3), + new State_Func3_Called(p), + new State_Return(3), + new State_Func4_Called(p, 400), + new State_Return(4), + new State_Func4_Called(p, 400), + new State_Return(4), + NULL), "Part 2.1"); + + // Unhook them + SH_REMOVE_HOOK(TheWall, Func1, p, SH_STATIC(Handler_Func1), false); + SH_REMOVE_HOOK(TheWall, Func2, p, SH_STATIC(Handler_Func2), false); + SH_REMOVE_HOOK(TheWall, Func3, p, SH_STATIC(Handler_Func3), false); + SH_REMOVE_HOOK(TheWall, Func4, p, SH_STATIC(Handler_Func4), false); + + // 3) + // Hook each function manually, call them + + SH_ADD_MANUALHOOK(TheWall_Func1, p, SH_STATIC(Handler_Func1), false); + SH_ADD_MANUALHOOK(TheWall_Func2, p, SH_STATIC(Handler_Func2), false); + SH_ADD_MANUALHOOK(TheWall_Func3, p, SH_STATIC(Handler_Func3), false); + SH_ADD_MANUALHOOK(TheWall_Func4, p, SH_STATIC(Handler_Func4), false); + + p->Func1(); + p->Func2(200); + ADD_STATE(State_Return(p->Func3())); + ADD_STATE(State_Return(p->Func4(400))); + + CHECK_STATES((&g_States, + new State_Func1H_Called(p), + new State_Func1_Called(p), + new State_Func2H_Called(p, 200), + new State_Func2_Called(p, 0x87654321), + new State_Func3H_Called(p), + new State_Func3_Called(p), + new State_Return(3), + new State_Func4H_Called(p, 400), + new State_Func4_Called(p, 0x12345678), + new State_Return(4), + NULL), "Part 3"); + + // Now through the mcallclass + + // Call them through the mcallclass + // 3.1) + // Now call each function through the manual call class, using the hook decl and manually + SH_MCALL(p, TheWall_Func1)(); + SH_MCALL2(p, MFP_Func1(), 0, 0, 0)(); + SH_MCALL(p, TheWall_Func2)(200); + SH_MCALL2(p, MFP_Func2(), 1, 0, 0)(200); + ADD_STATE(State_Return(SH_MCALL(p, TheWall_Func3)())); + ADD_STATE(State_Return(SH_MCALL2(p, MFP_Func3(), 2, 0, 0)())); + ADD_STATE(State_Return(SH_MCALL(p, TheWall_Func4)(400))); + ADD_STATE(State_Return(SH_MCALL2(p, MFP_Func4(), 3, 0, 0)(400))); + + CHECK_STATES((&g_States, + new State_Func1_Called(p), + new State_Func1_Called(p), + new State_Func2_Called(p, 200), + new State_Func2_Called(p, 200), + new State_Func3_Called(p), + new State_Return(3), + new State_Func3_Called(p), + new State_Return(3), + new State_Func4_Called(p, 400), + new State_Return(4), + new State_Func4_Called(p, 400), + new State_Return(4), + NULL), "Part 3.1"); + + // Unhook them + SH_REMOVE_MANUALHOOK(TheWall_Func1, p, SH_STATIC(Handler_Func1), false); + SH_REMOVE_MANUALHOOK(TheWall_Func2, p, SH_STATIC(Handler_Func2), false); + SH_REMOVE_MANUALHOOK(TheWall_Func3, p, SH_STATIC(Handler_Func3), false); + SH_REMOVE_MANUALHOOK(TheWall_Func4, p, SH_STATIC(Handler_Func4), false); + + // 4) + // Hook each function manually, then normally, call, unhook + + AnotherBrick handler_inst; + + // Why this? + // 1) tests sh_add_manualhook + // 2) in my tests, the proto of the manual hook was not equal to the proto of the auto hook + // (because there are no attribs for manual hooks). + // sourcehook.cpp did a !strcmp(..), so it assigned a new hook manager even though there + // already was one for this vfnptr. This hook manager stored the pointer of the original + // hook manager's hookfunc as the orig pointer - everything seemingly worked. + // The problem with this is that returning MRES_SUPERCEDE (as AnotherBrick::Handler_Func1 + // does) will supercede the second hook func from being called - thus bypassing the call + // of the auto hook here. + SH_ADD_MANUALHOOK(TheWall_Func1, p, SH_MEMBER(&handler_inst, &AnotherBrick::Handler_Func1), false); + SH_ADD_MANUALHOOK(TheWall_Func2, p, SH_STATIC(Handler_Func2), false); + SH_ADD_MANUALHOOK(TheWall_Func3, p, SH_STATIC(Handler_Func3), false); + SH_ADD_MANUALHOOK(TheWall_Func4, p, SH_STATIC(Handler_Func4), false); + + SH_ADD_HOOK(TheWall, Func1, p, SH_STATIC(Handler_Func1), false); + SH_ADD_HOOK(TheWall, Func2, p, SH_STATIC(Handler_Func2), false); + SH_ADD_HOOK(TheWall, Func3, p, SH_STATIC(Handler_Func3), false); + SH_ADD_HOOK(TheWall, Func4, p, SH_STATIC(Handler_Func4), false); + + p->Func1(); + p->Func2(200); + ADD_STATE(State_Return(p->Func3())); + ADD_STATE(State_Return(p->Func4(400))); + + CHECK_STATES((&g_States, + new State_Func1H_Called(p), + new State_Func1H_Called(p), + //new State_Func1_Called(p), + new State_Func2H_Called(p, 200), + new State_Func2H_Called(p, 0x87654321), + new State_Func2_Called(p, 0x87654321), + new State_Func3H_Called(p), + new State_Func3H_Called(p), + new State_Func3_Called(p), + new State_Return(3), + new State_Func4H_Called(p, 400), + new State_Func4H_Called(p, 0x12345678), + new State_Func4_Called(p, 0x12345678), + new State_Return(4), + NULL), "Part 4"); + + SH_REMOVE_MANUALHOOK(TheWall_Func1, p, SH_MEMBER(&handler_inst, &AnotherBrick::Handler_Func1), false); + SH_REMOVE_MANUALHOOK(TheWall_Func2, p, SH_STATIC(Handler_Func2), false); + SH_REMOVE_MANUALHOOK(TheWall_Func3, p, SH_STATIC(Handler_Func3), false); + SH_REMOVE_MANUALHOOK(TheWall_Func4, p, SH_STATIC(Handler_Func4), false); + + SH_REMOVE_HOOK(TheWall, Func1, p, SH_STATIC(Handler_Func1), false); + SH_REMOVE_HOOK(TheWall, Func2, p, SH_STATIC(Handler_Func2), false); + SH_REMOVE_HOOK(TheWall, Func3, p, SH_STATIC(Handler_Func3), false); + SH_REMOVE_HOOK(TheWall, Func4, p, SH_STATIC(Handler_Func4), false); + + // 5) Reconfigure TheWall_Func1 to actually hook Func5: + SH_MANUALHOOK_RECONFIGURE(TheWall_Func1, 4, 0, 0); + SH_ADD_MANUALHOOK(TheWall_Func1, p, SH_STATIC(Handler_Func1), false); + + p->Func5(); + + CHECK_STATES((&g_States, + new State_Func1H_Called(p), + new State_Func5_Called(p), + NULL), "Part 5"); + + // 6) Test auto-remove on reconfig + SH_MANUALHOOK_RECONFIGURE(TheWall_Func1, 0, 0, 0); + + p->Func1(); + p->Func5(); + + CHECK_STATES((&g_States, + new State_Func1_Called(p), + new State_Func5_Called(p), + NULL), "Part 6"); + + return true; +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/testmulti.cpp b/utils/mmsource/core-legacy/sourcehook/test/testmulti.cpp new file mode 100644 index 00000000..af5555c4 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/testmulti.cpp @@ -0,0 +1,106 @@ +#include +#include "sourcehook.h" +#include "sourcehook_test.h" +#include "testevents.h" + +// This should probably be done the other way round! +#ifdef __linux__ +#define _snprintf snprintf +#endif + +namespace +{ + SourceHook::ISourceHook *g_SHPtr; + SourceHook::Plugin g_PLID; + + unsigned int g_callcount[10]; + + class VMultiTest + { + public: + VMultiTest(unsigned int index) : m_idx(index) + { + } + public: + virtual void HookTarget() + { + } + virtual void Notify() + { + g_callcount[this->m_idx]++; + } + private: + unsigned int m_idx; + }; + + void HookFunction() + { + VMultiTest *pv = META_IFACEPTR(VMultiTest); + pv->Notify(); + } + + SH_DECL_HOOK0_void(VMultiTest, HookTarget, SH_NOATTRIB, false); +}; + +bool TestMulti(std::string &error) +{ + GET_SHPTR(g_SHPtr); + g_PLID = 1337; + + VMultiTest **pv = new VMultiTest *[10]; + for (unsigned int i=0; i<10; i++) + pv[i] = new VMultiTest(i); + + + for (unsigned int i=0; i<10; i++) + SH_ADD_HOOK(VMultiTest, HookTarget, pv[i], SH_STATIC(HookFunction), false); + + pv[0]->HookTarget(); + + if (g_callcount[0] != 1) + { + error.assign("g_callcount[0] != 0"); + return false; + } + + for (unsigned int i=1; i<10; i++) + { + if (g_callcount[i]) + { + error.assign("g_callcount[n] != 0"); + return false; + } + } + + SH_REMOVE_HOOK(VMultiTest, HookTarget, pv[0], SH_STATIC(HookFunction), false); + + for (unsigned int i=1; i<10; i++) + pv[i]->HookTarget(); + + if (g_callcount[0] != 1) + { + error.assign("g_callcount[0] != 0"); + return false; + } + + for (unsigned int i=1; i<10; i++) + { + if (g_callcount[i] != 1) + { + char err[256]; + _snprintf(err, sizeof(err)-1, "g_callcount[%d] != 1", i); + error.assign(err); + return false; + } + } + + for (unsigned int i=1; i<10; i++) + { + SH_REMOVE_HOOK(VMultiTest, HookTarget, pv[1], SH_STATIC(HookFunction), false); + delete pv[i]; + } + + delete [] pv; + + return true; +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/testrecall.cpp b/utils/mmsource/core-legacy/sourcehook/test/testrecall.cpp new file mode 100644 index 00000000..5277b176 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/testrecall.cpp @@ -0,0 +1,231 @@ +#include +#include "sourcehook.h" +#include "sourcehook_test.h" +#include "testevents.h" + +// TESTRECALL +// Test modifying parameters from hook handlers + +namespace +{ + StateList g_States; + SourceHook::ISourceHook *g_SHPtr; + SourceHook::Plugin g_PLID; + + MAKE_STATE_1(State_Func1, int); + MAKE_STATE_1(State_H1_Func1, int); + MAKE_STATE_1(State_H2_Func1, int); + MAKE_STATE_2(State_HP_Func1, int, void*); + + MAKE_STATE_1(State_Func2, int); + MAKE_STATE_1(State_H1_Func2, int); + MAKE_STATE_1(State_H2_Func2, int); + MAKE_STATE_2(State_HP_Func2, int, int); + + MAKE_STATE_2(State_Func22, int, int); + MAKE_STATE_2(State_H1_Func22, int, int); + MAKE_STATE_2(State_HP1_Func22, int, int); + MAKE_STATE_2(State_HP2_Func22, int, int); + + struct Test + { + virtual void Func1(int a) + { + ADD_STATE(State_Func1(a)); + } + + virtual int Func2(int a) + { + ADD_STATE(State_Func2(a)); + return 1000; + } + + // Overloaded version + virtual int Func2(int a, int b) + { + ADD_STATE(State_Func22(a, b)); + return 0xDEADFC; + } + }; + + // GCC's optimizer is too good. I had to add this in order to make it execute a virtual table lookup! + struct Whatever : Test + { + }; + + void Handler1_Func1(int a) + { + ADD_STATE(State_H1_Func1(a)); + RETURN_META_NEWPARAMS(MRES_IGNORED, &Test::Func1, (5)); + } + void Handler2_Func1(int a) + { + ADD_STATE(State_H2_Func1(a)); + RETURN_META_NEWPARAMS(MRES_IGNORED, &Test::Func1, (a - 5)); + } + void HandlerPost_Func1(int a) + { + ADD_STATE(State_HP_Func1(a, META_IFACEPTR(void))); + } + + + int Handler1_Func2(int a) + { + ADD_STATE(State_H1_Func2(a)); + // Pfeeehhh, ugly, I know, but I had to test it :) + RETURN_META_VALUE_NEWPARAMS(MRES_OVERRIDE, 500, + static_cast(&Test::Func2), (a - 10)); + } + + int Handler2_Func2(int a) + { + ADD_STATE(State_H2_Func2(a)); + RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, 0, + static_cast(&Test::Func2), (a - 10)); + } + + int HandlerPost_Func2(int a) + { + ADD_STATE(State_HP_Func2(a, META_RESULT_ORIG_RET(int))); + RETURN_META_VALUE(MRES_IGNORED, 0); + } + + int Handler1_Func22(int a, int b) + { + ADD_STATE(State_H1_Func22(a, b)); + RETURN_META_VALUE(MRES_IGNORED, 0); + } + + int HandlerPost1_Func22(int a, int b) + { + ADD_STATE(State_HP1_Func22(a, b)); + RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, 0, static_cast(&Test::Func2), (1, 2)); + } + + int HandlerPost1A_Func22(int a, int b) + { + ADD_STATE(State_HP1_Func22(a, b)); + RETURN_META_VALUE_NEWPARAMS(MRES_OVERRIDE, 0, static_cast(&Test::Func2), (1, 2)); + } + + int HandlerPost2_Func22(int a, int b) + { + ADD_STATE(State_HP2_Func22(a, b)); + RETURN_META_VALUE(MRES_IGNORED, 0); + } + + SH_DECL_HOOK1_void(Test, Func1, SH_NOATTRIB, 0, int); + SH_DECL_HOOK1(Test, Func2, SH_NOATTRIB, 0, int, int); + SH_DECL_HOOK2(Test, Func2, SH_NOATTRIB, 1, int, int, int); +} + +bool TestRecall(std::string &error) +{ + GET_SHPTR(g_SHPtr); + g_PLID = 1337; + + Whatever inst; + Test *ptr = &inst; + + SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler1_Func1), false); + SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false); + SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(HandlerPost_Func1), true); + + ptr->Func1(77); + + CHECK_STATES((&g_States, + new State_H1_Func1(77), + new State_H2_Func1(5), + new State_Func1(0), + new State_HP_Func1(0, ptr), + NULL), "Part 1"); + + SH_REMOVE_HOOK(Test, Func1, ptr, SH_STATIC(Handler1_Func1), false); + SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false); + SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false); + SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false); + + ptr->Func1(77); + + CHECK_STATES((&g_States, + new State_H2_Func1(77), + new State_H2_Func1(72), + new State_H2_Func1(67), + new State_H2_Func1(62), + new State_Func1(57), + new State_HP_Func1(57, ptr), + NULL), "Part 2"); + + SH_REMOVE_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false); + SH_REMOVE_HOOK(Test, Func1, ptr, SH_STATIC(HandlerPost_Func1), true); + + ptr->Func1(77); + + CHECK_STATES((&g_States, + new State_Func1(77), + NULL), "Part 3"); + + // Func2 + + SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(Handler1_Func2), false); + SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost_Func2), true); + + int a = ptr->Func2(77); + CHECK_STATES((&g_States, + new State_H1_Func2(77), + new State_Func2(67), + new State_HP_Func2(67, 1000), // 1000 because it's the ORIG_RET + NULL), "Part 4"); + + CHECK_COND(a == 500, "Part 4.1"); + + // Func2, with other handler + SH_REMOVE_HOOK(Test, Func2, ptr, SH_STATIC(Handler1_Func2), false); + SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(Handler2_Func2), false); + + a = ptr->Func2(77); + CHECK_STATES((&g_States, + new State_H2_Func2(77), + new State_Func2(67), + new State_HP_Func2(67, 1000), // 1000 because it's the ORIG_RET + NULL), "Part 4.2"); + + CHECK_COND(a == 1000, "Part 4.2.1"); // Should return 1000 as well. + + // Func22 -> post recalls + + // 1) WITH OVERRIDE + + SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(Handler1_Func22), false); + SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost1A_Func22), true); + SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost2_Func22), true); + + a = ptr->Func2(10, 11); + CHECK_STATES((&g_States, + new State_H1_Func22(10, 11), + new State_Func22(10, 11), + new State_HP1_Func22(10, 11), + new State_HP2_Func22(1, 2), + NULL), "Part 5"); + + CHECK_COND(a == 0, "Part 5.1"); + + // 2) WITH IGNORE + SH_REMOVE_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost1A_Func22), true); + SH_REMOVE_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost2_Func22), true); + + SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost1_Func22), true); + SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost2_Func22), true); + + a = ptr->Func2(10, 11); + CHECK_STATES((&g_States, + new State_H1_Func22(10, 11), + new State_Func22(10, 11), + new State_HP1_Func22(10, 11), + new State_HP2_Func22(1, 2), + NULL), "Part 5"); + + CHECK_COND(a == 0xDEADFC, "Part 5.1"); + + return true; +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/testreentr.cpp b/utils/mmsource/core-legacy/sourcehook/test/testreentr.cpp new file mode 100644 index 00000000..e0b69741 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/testreentr.cpp @@ -0,0 +1,609 @@ +// Reentrancy test +// = calling hooks from hook handlers, etc + +#include +#include "sourcehook_test.h" +#include "testevents.h" + +namespace +{ + StateList g_States; + SourceHook::ISourceHook *g_SHPtr; + SourceHook::Plugin g_PLID; + + struct C1; + struct C2; + struct C3; + struct C4; + struct C5; + struct C6; + struct C7; + struct C8; + + C1 *g_pC1; + C2 *g_pC2; + C3 *g_pC3; + C4 *g_pC4; + C5 *g_pC5; + C6 *g_pC6; + C7 *g_pC7; + C8 *g_pC8; + + // param1: This pointer + MAKE_STATE_1(State_C1_F, C1*); + MAKE_STATE_1(State_C2_F, C2*); + MAKE_STATE_1(State_C3_F, C3*); + MAKE_STATE_1(State_C4_F, C4*); + MAKE_STATE_1(State_C5_F, C5*); + MAKE_STATE_1(State_C6_F, C6*); + MAKE_STATE_1(State_C7_F, C7*); + MAKE_STATE_1(State_C8_F, C8*); + + MAKE_STATE_1(State_C1_G, C1*); + MAKE_STATE_1(State_C2_G, C2*); + MAKE_STATE_1(State_C3_G, C3*); + MAKE_STATE_1(State_C4_G, C4*); + MAKE_STATE_1(State_C5_G, C5*); + MAKE_STATE_1(State_C6_G, C6*); + MAKE_STATE_1(State_C7_G, C7*); + MAKE_STATE_1(State_C8_G, C8*); + + MAKE_STATE_1(State_H_C1_F, C1*); + MAKE_STATE_1(State_H_C2_F, C2*); + MAKE_STATE_1(State_H_C3_F, C3*); + MAKE_STATE_1(State_H_C4_F, C4*); + MAKE_STATE_1(State_H_C5_F, C5*); + MAKE_STATE_1(State_H_C6_F, C6*); + MAKE_STATE_1(State_H_C7_F, C7*); + MAKE_STATE_1(State_H_C8_F, C8*); + + MAKE_STATE_1(State_H_C1_G, C1*); + MAKE_STATE_1(State_H_C2_G, C2*); + MAKE_STATE_1(State_H_C3_G, C3*); + MAKE_STATE_1(State_H_C4_G, C4*); + MAKE_STATE_1(State_H_C5_G, C5*); + MAKE_STATE_1(State_H_C6_G, C6*); + MAKE_STATE_1(State_H_C7_G, C7*); + MAKE_STATE_1(State_H_C8_G, C8*); + + MAKE_STATE_1(State_H2_C4_G, C4*); + + int g_TestID; + + struct C1 + { + virtual void F() + { + ADD_STATE(State_C1_F(this)); + } + virtual int G() + { + ADD_STATE(State_C1_G(this)); + return 1; + } + }; + + struct C2 + { + virtual void F() + { + ADD_STATE(State_C2_F(this)); + } + virtual int G() + { + ADD_STATE(State_C2_G(this)); + return 2; + } + }; + struct C3 + { + virtual void F() + { + ADD_STATE(State_C3_F(this)); + } + virtual int G() + { + ADD_STATE(State_C3_G(this)); + return 3; + } + }; + struct C4 + { + virtual void F() + { + ADD_STATE(State_C4_F(this)); + } + virtual int G() + { + ADD_STATE(State_C4_G(this)); + return 4; + } + }; + struct C5 + { + virtual void F() + { + ADD_STATE(State_C5_F(this)); + } + virtual int G() + { + ADD_STATE(State_C5_G(this)); + return 5; + } + }; + struct C6 + { + virtual void F() + { + ADD_STATE(State_C6_F(this)); + } + virtual int G() + { + ADD_STATE(State_C6_G(this)); + return 6; + } + }; + struct C7 + { + virtual void F() + { + ADD_STATE(State_C7_F(this)); + } + virtual int G() + { + ADD_STATE(State_C7_G(this)); + return 7; + } + }; + struct C8 + { + virtual void F() + { + ADD_STATE(State_C8_F(this)); + } + virtual int G() + { + ADD_STATE(State_C8_G(this)); + return 8; + } + }; + + struct C1_Derived : public C1 {}; + struct C2_Derived : public C2 {}; + struct C3_Derived : public C3 {}; + struct C4_Derived : public C4 {}; + struct C5_Derived : public C5 {}; + struct C6_Derived : public C6 {}; + struct C7_Derived : public C7 {}; + struct C8_Derived : public C8 {}; + + SH_DECL_HOOK0_void(C1, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C1, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C2, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C2, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C3, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C3, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C4, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C4, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C5, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C5, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C6, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C6, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C7, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C7, G, SH_NOATTRIB, 0, int); + SH_DECL_HOOK0_void(C8, F, SH_NOATTRIB, 0); + SH_DECL_HOOK0(C8, G, SH_NOATTRIB, 0, int); + + void Handler_C1_F() + { + ADD_STATE(State_H_C1_F(META_IFACEPTR(C1))); + g_pC1->G(); + } + int Handler_C1_G() + { + ADD_STATE(State_H_C1_G(META_IFACEPTR(C1))); + g_pC2->F(); + return 1; + } + void Handler_C2_F() + { + ADD_STATE(State_H_C2_F(META_IFACEPTR(C2))); + g_pC2->G(); + } + int Handler_C2_G() + { + ADD_STATE(State_H_C2_G(META_IFACEPTR(C2))); + g_pC3->F(); + return 2; + } + void Handler_C3_F() + { + ADD_STATE(State_H_C3_F(META_IFACEPTR(C3))); + g_pC3->G(); + } + int Handler_C3_G() + { + ADD_STATE(State_H_C3_G(META_IFACEPTR(C3))); + g_pC4->F(); + return 3; + } + void Handler_C4_F() + { + ADD_STATE(State_H_C4_F(META_IFACEPTR(C4))); + g_pC4->G(); + } + int Handler_C4_G() + { + ADD_STATE(State_H_C4_G(META_IFACEPTR(C4))); + g_pC5->F(); + return 4; + } + int Handler2_C4_G() + { + ADD_STATE(State_H2_C4_G(META_IFACEPTR(C4))); + return 4; + } + void Handler_C5_F() + { + ADD_STATE(State_H_C5_F(META_IFACEPTR(C5))); + g_pC5->G(); + } + int Handler_C5_G() + { + ADD_STATE(State_H_C5_G(META_IFACEPTR(C5))); + g_pC6->F(); + return 5; + } + void Handler_C6_F() + { + ADD_STATE(State_H_C6_F(META_IFACEPTR(C6))); + g_pC6->G(); + } + int Handler_C6_G() + { + ADD_STATE(State_H_C6_G(META_IFACEPTR(C6))); + g_pC7->F(); + return 6; + } + void Handler_C7_F() + { + if (g_TestID == 1 || g_TestID == 2) + SH_REMOVE_HOOK(C4, G, g_pC4, SH_STATIC(Handler2_C4_G), false); + if (g_TestID == 2) + SH_REMOVE_HOOK(C4, G, g_pC4, SH_STATIC(Handler_C4_G), false); + + ADD_STATE(State_H_C7_F(META_IFACEPTR(C7))); + g_pC7->G(); + } + int Handler_C7_G() + { + ADD_STATE(State_H_C7_G(META_IFACEPTR(C7))); + g_pC8->F(); + return 7; + } + void Handler_C8_F() + { + ADD_STATE(State_H_C8_F(META_IFACEPTR(C8))); + g_pC8->G(); + } + int Handler_C8_G() + { + ADD_STATE(State_H_C8_G(META_IFACEPTR(C8))); + return 8; + } + + C1_Derived g_C1; + C2_Derived g_C2; + C3_Derived g_C3; + C4_Derived g_C4; + C5_Derived g_C5; + C6_Derived g_C6; + C7_Derived g_C7; + C8_Derived g_C8; +} + +bool TestReentr(std::string &error) +{ + GET_SHPTR(g_SHPtr); + g_PLID = 1337; + + g_pC1 = &g_C1; + g_pC2 = &g_C2; + g_pC3 = &g_C3; + g_pC4 = &g_C4; + g_pC5 = &g_C5; + g_pC6 = &g_C6; + g_pC7 = &g_C7; + g_pC8 = &g_C8; + + SH_ADD_HOOK(C1, F, g_pC1, SH_STATIC(Handler_C1_F), false); + SH_ADD_HOOK(C1, G, g_pC1, SH_STATIC(Handler_C1_G), false); + SH_ADD_HOOK(C2, F, g_pC2, SH_STATIC(Handler_C2_F), false); + SH_ADD_HOOK(C2, G, g_pC2, SH_STATIC(Handler_C2_G), false); + SH_ADD_HOOK(C3, F, g_pC3, SH_STATIC(Handler_C3_F), false); + SH_ADD_HOOK(C3, G, g_pC3, SH_STATIC(Handler_C3_G), false); + SH_ADD_HOOK(C4, F, g_pC4, SH_STATIC(Handler_C4_F), false); + SH_ADD_HOOK(C4, G, g_pC4, SH_STATIC(Handler_C4_G), false); + SH_ADD_HOOK(C5, F, g_pC5, SH_STATIC(Handler_C5_F), false); + SH_ADD_HOOK(C5, G, g_pC5, SH_STATIC(Handler_C5_G), false); + SH_ADD_HOOK(C6, F, g_pC6, SH_STATIC(Handler_C6_F), false); + SH_ADD_HOOK(C6, G, g_pC6, SH_STATIC(Handler_C6_G), false); + SH_ADD_HOOK(C7, F, g_pC7, SH_STATIC(Handler_C7_F), false); + SH_ADD_HOOK(C7, G, g_pC7, SH_STATIC(Handler_C7_G), false); + SH_ADD_HOOK(C8, F, g_pC8, SH_STATIC(Handler_C8_F), false); + SH_ADD_HOOK(C8, G, g_pC8, SH_STATIC(Handler_C8_G), false); + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_H_C4_G(g_pC4), + new State_H_C5_F(g_pC5), + new State_H_C5_G(g_pC5), + new State_H_C6_F(g_pC6), + new State_H_C6_G(g_pC6), + new State_H_C7_F(g_pC7), + new State_H_C7_G(g_pC7), + new State_H_C8_F(g_pC8), + new State_H_C8_G(g_pC8), + new State_C8_G(g_pC8), + new State_C8_F(g_pC8), + new State_C7_G(g_pC7), + new State_C7_F(g_pC7), + new State_C6_G(g_pC6), + new State_C6_F(g_pC6), + new State_C5_G(g_pC5), + new State_C5_F(g_pC5), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "1"); + + + SH_ADD_HOOK(C4, G, g_pC4, SH_STATIC(Handler2_C4_G), false); + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_H_C4_G(g_pC4), + new State_H_C5_F(g_pC5), + new State_H_C5_G(g_pC5), + new State_H_C6_F(g_pC6), + new State_H_C6_G(g_pC6), + new State_H_C7_F(g_pC7), + new State_H_C7_G(g_pC7), + new State_H_C8_F(g_pC8), + new State_H_C8_G(g_pC8), + new State_C8_G(g_pC8), + new State_C8_F(g_pC8), + new State_C7_G(g_pC7), + new State_C7_F(g_pC7), + new State_C6_G(g_pC6), + new State_C6_F(g_pC6), + new State_C5_G(g_pC5), + new State_C5_F(g_pC5), + new State_H2_C4_G(g_pC4), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "2"); + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_H_C4_G(g_pC4), + new State_H_C5_F(g_pC5), + new State_H_C5_G(g_pC5), + new State_H_C6_F(g_pC6), + new State_H_C6_G(g_pC6), + new State_H_C7_F(g_pC7), + new State_H_C7_G(g_pC7), + new State_H_C8_F(g_pC8), + new State_H_C8_G(g_pC8), + new State_C8_G(g_pC8), + new State_C8_F(g_pC8), + new State_C7_G(g_pC7), + new State_C7_F(g_pC7), + new State_C6_G(g_pC6), + new State_C6_F(g_pC6), + new State_C5_G(g_pC5), + new State_C5_F(g_pC5), + new State_H2_C4_G(g_pC4), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "3"); + + g_TestID = 1; + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_H_C4_G(g_pC4), + new State_H_C5_F(g_pC5), + new State_H_C5_G(g_pC5), + new State_H_C6_F(g_pC6), + new State_H_C6_G(g_pC6), + new State_H_C7_F(g_pC7), + new State_H_C7_G(g_pC7), + new State_H_C8_F(g_pC8), + new State_H_C8_G(g_pC8), + new State_C8_G(g_pC8), + new State_C8_F(g_pC8), + new State_C7_G(g_pC7), + new State_C7_F(g_pC7), + new State_C6_G(g_pC6), + new State_C6_F(g_pC6), + new State_C5_G(g_pC5), + new State_C5_F(g_pC5), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "4"); + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_H_C4_G(g_pC4), + new State_H_C5_F(g_pC5), + new State_H_C5_G(g_pC5), + new State_H_C6_F(g_pC6), + new State_H_C6_G(g_pC6), + new State_H_C7_F(g_pC7), + new State_H_C7_G(g_pC7), + new State_H_C8_F(g_pC8), + new State_H_C8_G(g_pC8), + new State_C8_G(g_pC8), + new State_C8_F(g_pC8), + new State_C7_G(g_pC7), + new State_C7_F(g_pC7), + new State_C6_G(g_pC6), + new State_C6_F(g_pC6), + new State_C5_G(g_pC5), + new State_C5_F(g_pC5), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "5"); + + + + SH_ADD_HOOK(C4, G, g_pC4, SH_STATIC(Handler2_C4_G), false); + + g_TestID = 2; + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_H_C4_G(g_pC4), + new State_H_C5_F(g_pC5), + new State_H_C5_G(g_pC5), + new State_H_C6_F(g_pC6), + new State_H_C6_G(g_pC6), + new State_H_C7_F(g_pC7), + new State_H_C7_G(g_pC7), + new State_H_C8_F(g_pC8), + new State_H_C8_G(g_pC8), + new State_C8_G(g_pC8), + new State_C8_F(g_pC8), + new State_C7_G(g_pC7), + new State_C7_F(g_pC7), + new State_C6_G(g_pC6), + new State_C6_F(g_pC6), + new State_C5_G(g_pC5), + new State_C5_F(g_pC5), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "6"); + + g_pC1->F(); + + CHECK_STATES((&g_States, + new State_H_C1_F(g_pC1), + new State_H_C1_G(g_pC1), + new State_H_C2_F(g_pC2), + new State_H_C2_G(g_pC2), + new State_H_C3_F(g_pC3), + new State_H_C3_G(g_pC3), + new State_H_C4_F(g_pC4), + new State_C4_G(g_pC4), + new State_C4_F(g_pC4), + new State_C3_G(g_pC3), + new State_C3_F(g_pC3), + new State_C2_G(g_pC2), + new State_C2_F(g_pC2), + new State_C1_G(g_pC1), + new State_C1_F(g_pC1), + NULL), "7"); + + SH_REMOVE_HOOK(C1, F, g_pC1, SH_STATIC(Handler_C1_F), false); + SH_REMOVE_HOOK(C1, G, g_pC1, SH_STATIC(Handler_C1_G), false); + SH_REMOVE_HOOK(C2, F, g_pC2, SH_STATIC(Handler_C2_F), false); + SH_REMOVE_HOOK(C2, G, g_pC2, SH_STATIC(Handler_C2_G), false); + SH_REMOVE_HOOK(C3, F, g_pC3, SH_STATIC(Handler_C3_F), false); + SH_REMOVE_HOOK(C3, G, g_pC3, SH_STATIC(Handler_C3_G), false); + SH_REMOVE_HOOK(C4, F, g_pC4, SH_STATIC(Handler_C4_F), false); + SH_REMOVE_HOOK(C4, G, g_pC4, SH_STATIC(Handler_C4_G), false); + SH_REMOVE_HOOK(C5, F, g_pC5, SH_STATIC(Handler_C5_F), false); + SH_REMOVE_HOOK(C5, G, g_pC5, SH_STATIC(Handler_C5_G), false); + SH_REMOVE_HOOK(C6, F, g_pC6, SH_STATIC(Handler_C6_F), false); + SH_REMOVE_HOOK(C6, G, g_pC6, SH_STATIC(Handler_C6_G), false); + SH_REMOVE_HOOK(C7, F, g_pC7, SH_STATIC(Handler_C7_F), false); + SH_REMOVE_HOOK(C7, G, g_pC7, SH_STATIC(Handler_C7_G), false); + SH_REMOVE_HOOK(C8, F, g_pC8, SH_STATIC(Handler_C8_F), false); + SH_REMOVE_HOOK(C8, G, g_pC8, SH_STATIC(Handler_C8_G), false); + + return true; +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/testref.cpp b/utils/mmsource/core-legacy/sourcehook/test/testref.cpp new file mode 100644 index 00000000..d718f3af --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/testref.cpp @@ -0,0 +1,162 @@ +#include "testevents.h" +#include "sourcehook_test.h" + +// References and private copy constructors and stuff like that! + +/* +BAILOPAN, 29.04.2006 21:51 : +onoto-san, interesting error from VS +we have this function: +void GabHaben(ISomething &sth); + +SomethingDerived sth; +and SH_CALL(cc, &WHAT::GabHaben)(sth); +"No copy constructor available for class 'SomethingDerived'" +*/ + + +namespace +{ + StateList g_States; + SourceHook::ISourceHook *g_SHPtr; + SourceHook::Plugin g_PLID; + + MAKE_STATE_1(State_Result, int); + MAKE_STATE_1(State_Result_InHook, int); + + class CBase + { + // Private copy constructor! + CBase(CBase &other) + { + } + public: + CBase() + { + } + + virtual int Func() + { + return 0; + } + }; + + class CDerived : public CBase + { + virtual int Func() + { + return 10; + } + }; + + // Complicated derived shit ! + class COtherWeirdBase + { + int member; + }; + class CDerived2 : private COtherWeirdBase, public CBase + { + int m_Return; + public: + CDerived2(int a) : m_Return(a) + { + } + + virtual int Func() + { + return m_Return; + } + }; + + class CHello + { + public: + virtual int Func(CBase &sth) + { + return sth.Func(); + } + }; + class CHelloDerived : public CHello { }; + + class CHook + { + public: + virtual int Func(CBase &sth) + { + ADD_STATE(State_Result_InHook(sth.Func())); + RETURN_META_VALUE(MRES_SUPERCEDE, 20); + } + }; + SH_DECL_HOOK1(CHello, Func, SH_NOATTRIB, 0, int, CBase&); +} + + +bool TestRef(std::string &error) +{ + GET_SHPTR(g_SHPtr); + g_PLID = 1; + + CBase base; + CDerived der; + CDerived2 der2(11); + CDerived2 der3(12); + CHelloDerived hello; + CHello *pHello = &hello; + CHook hook; + + ADD_STATE(State_Result(pHello->Func(base))); + ADD_STATE(State_Result(pHello->Func(der))); + ADD_STATE(State_Result(pHello->Func(der2))); + ADD_STATE(State_Result(pHello->Func(der3))); + + CHECK_STATES((&g_States, + new State_Result(0), + new State_Result(10), + new State_Result(11), + new State_Result(12), + NULL), "Part 1"); + + ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(base))); + ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(der))); + ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(der2))); + ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(der3))); + + CHECK_STATES((&g_States, + new State_Result(0), + new State_Result(10), + new State_Result(11), + new State_Result(12), + NULL), "Part 2"); + + SH_ADD_HOOK(CHello, Func, &hello, SH_MEMBER(&hook, &CHook::Func), false); + + ADD_STATE(State_Result(pHello->Func(base))); + ADD_STATE(State_Result(pHello->Func(der))); + ADD_STATE(State_Result(pHello->Func(der2))); + ADD_STATE(State_Result(pHello->Func(der3))); + + CHECK_STATES((&g_States, + new State_Result_InHook(0), + new State_Result(20), + new State_Result_InHook(10), + new State_Result(20), + new State_Result_InHook(11), + new State_Result(20), + new State_Result_InHook(12), + new State_Result(20), + NULL), "Part 3"); + + ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(base))); + ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(der))); + ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(der2))); + ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(der3))); + + CHECK_STATES((&g_States, + new State_Result(0), + new State_Result(10), + new State_Result(11), + new State_Result(12), + NULL), "Part 4"); + + return true; +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/testrefret.cpp b/utils/mmsource/core-legacy/sourcehook/test/testrefret.cpp new file mode 100644 index 00000000..0b55ed0b --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/testrefret.cpp @@ -0,0 +1,202 @@ +#include "testevents.h" +#include "sourcehook_test.h" + +// Tests support for functions which return references + +namespace +{ + StateList g_States; + SourceHook::ISourceHook *g_SHPtr; + SourceHook::Plugin g_PLID; + + MAKE_STATE_1(State_Func1_Pre1, int*); // p1: the ref Func1_Pre1 is going to return + MAKE_STATE_3(State_Func1_Pre2, META_RES, int*, int*); // p1: current status + // p2: override ret + // p3: what this handler is going to supercede with + MAKE_STATE_1(State_Func1, int*); // p1: the ref Func1 is going to return + MAKE_STATE_2(State_Func1_Post1, int*, int*); // p1: orig_ret; p2: override_ret + MAKE_STATE_1(State_Func1_Post2, int*); // p1: what it's going to return + MAKE_STATE_1(State_Func1_Ret, int*); // p1: the ref it returned + + + MAKE_STATE_2(State_Func2_Pre1, int, const int*); // p1: func's p1; p2: what it's going to ret + MAKE_STATE_2(State_Func2, int, const int*); // p1: func's p1; p2: what it's going to ret + MAKE_STATE_3(State_Func2_Post1, int, const int*, const int*); // p1: func's p1; p2: orig ret; p3: override ret + MAKE_STATE_1(State_Func2_Ret, const int*); // p1: ret + + int g_Var; + + class Test + { + public: + int m_Var1; + int m_Var2; + + Test() : m_Var1(87) + { + } + + virtual int& Func1() + { + ADD_STATE(State_Func1(&m_Var1)); + return m_Var1; + } + virtual const int& Func2(int p1) + { + ADD_STATE(State_Func2(p1, &m_Var2)); + m_Var2 = p1; + return m_Var2; + } + }; + + class Whatever : public Test + { + }; + + class CHook + { + public: + int m_Var; + virtual int& Func1_Pre1() + { + ADD_STATE(State_Func1_Pre1(&m_Var)); + RETURN_META_VALUE(MRES_OVERRIDE, m_Var); + } + virtual int &Func1_Pre2() + { + int &overrideret = META_RESULT_OVERRIDE_RET(int&); + overrideret = 1337; + ADD_STATE(State_Func1_Pre2(META_RESULT_STATUS, &overrideret, &g_Var)); + RETURN_META_VALUE(MRES_SUPERCEDE, g_Var); + } + virtual int& Func1_Post1() + { + ADD_STATE(State_Func1_Post1(&META_RESULT_ORIG_RET(int&), &META_RESULT_OVERRIDE_RET(int&))); + RETURN_META_NOREF(MRES_IGNORED, int&); + } + virtual int& Func1_Post2() + { + ADD_STATE(State_Func1_Post2(&m_Var)); + RETURN_META_VALUE(MRES_OVERRIDE, m_Var); + } + + virtual const int& Func2_Pre1(int p1) + { + ADD_STATE(State_Func2_Pre1(p1, &m_Var)); + RETURN_META_VALUE_NEWPARAMS(MRES_OVERRIDE, m_Var, static_cast(&Test::Func2), (1337)); + } + + virtual const int& Func2_Post1(int p1) + { + ADD_STATE(State_Func2_Post1(p1, &META_RESULT_ORIG_RET(int&), &META_RESULT_OVERRIDE_RET(int&))); + RETURN_META_NOREF(MRES_IGNORED, const int&); + } + }; + + SH_DECL_HOOK0(Test, Func1, SH_NOATTRIB, 0, int&); + SH_DECL_HOOK1(Test, Func2, SH_NOATTRIB, 0, const int&, int); +} + +bool TestRefRet(std::string &error) +{ + GET_SHPTR(g_SHPtr); + g_PLID = 1; + + Whatever test; + Test *pTest = &test; + CHook hook; + + int &ret1 = pTest->Func1(); + ADD_STATE(State_Func1_Ret(&ret1)); + + CHECK_STATES((&g_States, + new State_Func1(&test.m_Var1), + new State_Func1_Ret(&test.m_Var1), + NULL), "Part 1"); + + // Now add Func1_Pre1, which supercedes and returns hook.m_Var + SH_ADD_HOOK(Test, Func1, &test, SH_MEMBER(&hook, &CHook::Func1_Pre1), false); + + int &ret2 = pTest->Func1(); + ADD_STATE(State_Func1_Ret(&ret2)); + + CHECK_STATES((&g_States, + new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var + new State_Func1(&test.m_Var1), // Function says that it's going to return test.m_Var1 + new State_Func1_Ret(&hook.m_Var), // hook.m_Var is returned + NULL), "Part 2"); + + // Now add Func1_Post1, which only reports orig ret and override ret + SH_ADD_HOOK(Test, Func1, &test, SH_MEMBER(&hook, &CHook::Func1_Post1), true); + + int &ret3 = pTest->Func1(); + ADD_STATE(State_Func1_Ret(&ret3)); + + CHECK_STATES((&g_States, + new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var + new State_Func1(&test.m_Var1), // Function says that it's going to return test.m_Var1 + new State_Func1_Post1(&test.m_Var1, &hook.m_Var), // origret(=p1) is what it wanted to + // return, overrideret(=p2) is pre1's var + new State_Func1_Ret(&hook.m_Var), // hook.m_Var is returned + NULL), "Part 3"); + + // Now add Func1_Pre2, which supercedes and returns g_Var (it also sets the override ret from pre1 to 1337) + // and add Func1_Post2, which overrides and returns hook.m_Var again. + + SH_ADD_HOOK(Test, Func1, &test, SH_MEMBER(&hook, &CHook::Func1_Pre2), false); + SH_ADD_HOOK(Test, Func1, &test, SH_MEMBER(&hook, &CHook::Func1_Post2), true); + + int &ret4 = pTest->Func1(); + ADD_STATE(State_Func1_Ret(&ret4)); + + CHECK_STATES((&g_States, + new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var + new State_Func1_Pre2(MRES_OVERRIDE, // current status + &hook.m_Var, // override ret (which it set to 1337) + &g_Var), // what it's going to ret, AND supercede with + + new State_Func1_Post1(&g_Var, &g_Var), // origret(=p1) is what pre2 superceded with, + // so overrideret(=p2) has to be the same + new State_Func1_Post2(&hook.m_Var), // post2 is going to override with hook.m_Var again + new State_Func1_Ret(&hook.m_Var), // ==>>> hook.m_Var is returned + NULL), "Part 4"); + + CHECK_COND(hook.m_Var == 1337, "Part 4.1"); + + // Through a callclass + int &ret5 = SH_CALL(pTest, &Test::Func1)(); + ADD_STATE(State_Func1_Ret(&ret5)); + + CHECK_STATES((&g_States, + new State_Func1(&test.m_Var1), + new State_Func1_Ret(&test.m_Var1), + NULL), "Part 5"); + + + //////////////////////////////////////////////////////////////////////////////////////// + // Func2 tests + const int &ret21 = pTest->Func2(500); + ADD_STATE(State_Func2_Ret(&ret21)); + + CHECK_STATES((&g_States, + new State_Func2(500, &test.m_Var2), + new State_Func2_Ret(&test.m_Var2), + NULL), "Part 6"); + + SH_ADD_HOOK(Test, Func2, &test, SH_MEMBER(&hook, &CHook::Func2_Pre1), false); + SH_ADD_HOOK(Test, Func2, &test, SH_MEMBER(&hook, &CHook::Func2_Post1), true); + + const int &ret22 = pTest->Func2(500); + ADD_STATE(State_Func2_Ret(&ret22)); + + CHECK_STATES((&g_States, + new State_Func2_Pre1(500, &hook.m_Var), // p1 was 500; it's going to override with hook.m_Var; and also change p1 to 1337 + new State_Func2(1337, &test.m_Var2), // p1 was 1337; it's going to ret test.m_Var2 + new State_Func2_Post1(1337, // p1 was 1337 + &test.m_Var2, // orig ret was test.m_Var2 + &hook.m_Var), // override ret was hook.m_Var + new State_Func2_Ret(&hook.m_Var), // really returned hook.m_Var + NULL), "Part 7"); + + return true; +} diff --git a/utils/mmsource/core-legacy/sourcehook/test/testvphooks.cpp b/utils/mmsource/core-legacy/sourcehook/test/testvphooks.cpp new file mode 100644 index 00000000..acbeff8b --- /dev/null +++ b/utils/mmsource/core-legacy/sourcehook/test/testvphooks.cpp @@ -0,0 +1,260 @@ +#include +#include "sourcehook.h" +#include "sourcehook_test.h" +#include "testevents.h" + +// TEST VP HOOKS +// Test vfnptr-wide hooks + +namespace +{ + StateList g_States; + SourceHook::ISourceHook *g_SHPtr; + SourceHook::Plugin g_PLID; + + class IBase; + + MAKE_STATE_1(State_D1_Func1, IBase *); + MAKE_STATE_1(State_D2_Func1, IBase *); + MAKE_STATE_1(State_Func1_Pre, IBase *); + MAKE_STATE_1(State_Func1_Post, IBase *); + + MAKE_STATE_1(State_D1_Func2, IBase *); + MAKE_STATE_1(State_D2_Func2, IBase *); + MAKE_STATE_1(State_Func2_Pre, IBase *); + MAKE_STATE_1(State_Func2_Post, IBase *); + + MAKE_STATE_2(State_D1_Func3, IBase *, int); + MAKE_STATE_2(State_D2_Func3, IBase *, int); + MAKE_STATE_2(State_Func3_Pre, IBase *, int); + MAKE_STATE_2(State_Func3_Post, IBase *, int); + + class IBase + { + public: + virtual void Func1() = 0; + virtual void Func2() = 0; + virtual void Func3(int x) = 0; + }; + + class CDerived1 : public IBase + { + public: + virtual void Func1() + { + ADD_STATE(State_D1_Func1(this)); + } + virtual void Func2() + { + ADD_STATE(State_D1_Func2(this)); + } + virtual void Func3(int x) + { + ADD_STATE(State_D1_Func3(this, x)); + } + }; + + class CDerived2 : public IBase + { + public: + virtual void Func1() + { + ADD_STATE(State_D2_Func1(this)); + } + virtual void Func2() + { + ADD_STATE(State_D2_Func2(this)); + } + virtual void Func3(int x) + { + ADD_STATE(State_D2_Func3(this, x)); + } + }; + + void Handler_Func1_Pre() + { + ADD_STATE(State_Func1_Pre(META_IFACEPTR(IBase))); + } + void Handler_Func1_Post() + { + ADD_STATE(State_Func1_Post(META_IFACEPTR(IBase))); + } + int g_F2_Pre_HookToRemove = 0; + void Handler_Func2_Pre() + { + ADD_STATE(State_Func2_Pre(META_IFACEPTR(IBase))); + SH_REMOVE_HOOK_ID(g_F2_Pre_HookToRemove); + } + void Handler_Func2_Post() + { + ADD_STATE(State_Func2_Post(META_IFACEPTR(IBase))); + } + + + void Handler_Func3_Pre(int x) + { + ADD_STATE(State_Func3_Pre(META_IFACEPTR(IBase), x)); + + RETURN_META_NEWPARAMS(MRES_IGNORED, &IBase::Func3, (x+1)); + } + void Handler_Func3_Post(int x) + { + ADD_STATE(State_Func3_Post(META_IFACEPTR(IBase), x)); + } + + SH_DECL_HOOK0_void(IBase, Func1, SH_NOATTRIB, 0); + SH_DECL_HOOK0_void(IBase, Func2, SH_NOATTRIB, 0); + SH_DECL_HOOK1_void(IBase, Func3, SH_NOATTRIB, 0, int); + + SH_DECL_MANUALHOOK1_void(IBase_Func3_Manual, 2, 0, 0, int); +} + +bool TestVPHooks(std::string &error) +{ + GET_SHPTR(g_SHPtr); + g_PLID = 1337; + + CDerived1 d1i1; + CDerived1 d1i2; + CDerived2 d2i1; + + IBase *p_d1i1 = &d1i1; + IBase *p_d1i2 = &d1i2; + IBase *p_d2i1 = &d2i1; + + int hook1 = SH_ADD_VPHOOK(IBase, Func1, p_d1i1, SH_STATIC(Handler_Func1_Pre), false); + + p_d1i1->Func1(); + p_d1i2->Func1(); + p_d2i1->Func1(); + + CHECK_STATES((&g_States, + new State_Func1_Pre(p_d1i1), + new State_D1_Func1(p_d1i1), + + new State_Func1_Pre(p_d1i2), + new State_D1_Func1(p_d1i2), + + new State_D2_Func1(p_d2i1), + NULL), "Part 1"); + + SH_REMOVE_HOOK_ID(hook1); + + p_d1i1->Func1(); + p_d1i2->Func1(); + p_d2i1->Func1(); + + CHECK_STATES((&g_States, + new State_D1_Func1(p_d1i1), + + new State_D1_Func1(p_d1i2), + + new State_D2_Func1(p_d2i1), + NULL), "Part 2"); + + + // Normal hook, then vp hook + + int hook2 = SH_ADD_HOOK(IBase, Func1, p_d1i1, SH_STATIC(Handler_Func1_Pre), false); + hook1 = SH_ADD_VPHOOK(IBase, Func1, p_d1i1, SH_STATIC(Handler_Func1_Pre), false); + + p_d1i1->Func1(); + p_d1i2->Func1(); + p_d2i1->Func1(); + + CHECK_STATES((&g_States, + new State_Func1_Pre(p_d1i1), + new State_Func1_Pre(p_d1i1), + new State_D1_Func1(p_d1i1), + + new State_Func1_Pre(p_d1i2), + new State_D1_Func1(p_d1i2), + + new State_D2_Func1(p_d2i1), + NULL), "Part 3"); + + SH_REMOVE_HOOK_ID(hook1); + + p_d1i1->Func1(); + p_d1i2->Func1(); + p_d2i1->Func1(); + + CHECK_STATES((&g_States, + new State_Func1_Pre(p_d1i1), + new State_D1_Func1(p_d1i1), + + new State_D1_Func1(p_d1i2), + + new State_D2_Func1(p_d2i1), + NULL), "Part 4"); + + SH_REMOVE_HOOK_ID(hook2); + + p_d1i1->Func1(); + p_d1i2->Func1(); + p_d2i1->Func1(); + + CHECK_STATES((&g_States, + new State_D1_Func1(p_d1i1), + + new State_D1_Func1(p_d1i2), + + new State_D2_Func1(p_d2i1), + NULL), "Part 5"); + + // Test this: + // Normal hook AND vp hook on Func2 + // Func2's pre handler removes the VP hook. + + hook1 = SH_ADD_VPHOOK(IBase, Func2, p_d1i1, SH_STATIC(Handler_Func2_Pre), false); + hook2 = SH_ADD_HOOK(IBase, Func2, p_d1i1, SH_STATIC(Handler_Func2_Pre), false); + + g_F2_Pre_HookToRemove = hook1; + p_d1i1->Func2(); + p_d1i1->Func2(); + + CHECK_STATES((&g_States, + new State_Func2_Pre(p_d1i1), + new State_D1_Func2(p_d1i1), + + new State_Func2_Pre(p_d1i1), + new State_D1_Func2(p_d1i1), + + NULL), "Part 6"); + + SH_REMOVE_HOOK_ID(hook1); + + // Hook function 3: + // Using manualhook, VP + hook1 = SH_ADD_MANUALVPHOOK(IBase_Func3_Manual, p_d1i1, SH_STATIC(Handler_Func3_Pre), false); + + // Normally, VP + hook2 = SH_ADD_VPHOOK(IBase, Func3, p_d1i1, SH_STATIC(Handler_Func3_Pre), false); + + // Normally, no VP + int hook3 = SH_ADD_HOOK(IBase, Func3, p_d1i1, SH_STATIC(Handler_Func3_Pre), false); + + p_d1i1->Func3(1); + + CHECK_STATES((&g_States, + new State_Func3_Pre(p_d1i1, 1), // manual vp hook + new State_Func3_Pre(p_d1i1, 2), // normal vp hook + new State_Func3_Pre(p_d1i1, 3), // normal non-vp hook + + new State_D1_Func3(p_d1i1, 4), // function + + NULL), "Part 7.1"); + + p_d1i2->Func3(1); + + CHECK_STATES((&g_States, + new State_Func3_Pre(p_d1i2, 1), // manual vp hook + new State_Func3_Pre(p_d1i2, 2), // normal vp hook + + new State_D1_Func3(p_d1i2, 3), // function + + NULL), "Part 7.2"); + + return true; +} + diff --git a/utils/mmsource/core-legacy/sourcemm.cpp b/utils/mmsource/core-legacy/sourcemm.cpp new file mode 100644 index 00000000..c3d4d7c5 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcemm.cpp @@ -0,0 +1,656 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2010 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * Contributor(s): Scott "Damaged Soul" Ehlert + * : Pavol "PM OnoTo" Marko + * ============================ + */ + +#include +#include +#include +#include "sourcemm.h" +#include "concommands.h" +#include "CSmmAPI.h" +#include "CPlugin.h" +#include "util.h" +#include "iplayerinfo.h" +#include + +using namespace SourceMM; + +/** + * @brief Implementation of main SourceMM GameDLL functionality + * @file sourcemm.cpp + */ + +#undef CommandLine +DLL_IMPORT ICommandLine *CommandLine(); + +SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false); +SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool); +SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *); +SH_DECL_HOOK0(IServerGameDLL, GameInit, SH_NOATTRIB, false, bool); + +void LevelShutdown_handler(); +bool LevelInit_handler(char const *pMapName, + char const *pMapEntities, + char const *pOldLevel, + char const *pLandmarkName, + bool loadGame, + bool background); +bool GameInit_handler(); +int LoadPlugins(const char *filepath, const char *vdfpath); +int LoadVDFPluginsFromDir(const char *dir, int &skipped); +bool KVLoadFromFile(KeyValues *kv, + IBaseFileSystem *filesystem, + const char *resourceName, + const char *pathID = NULL); + +GameDllInfo g_GameDll = {false, NULL, NULL, NULL}; +EngineInfo g_Engine; +SourceHook::CSourceHookImpl g_SourceHook; +SourceHook::ISourceHook *g_SHPtr = &g_SourceHook; +SourceHook::String g_ModPath; +SourceHook::String g_MetamodPath; +PluginId g_PLID = Pl_Console; /* Technically, SourceMM is the "Console" plugin... :p */ +static bool bInFirstLevel = true; +bool g_bGameInit = false; +int g_GameDllVersion = 0; +static const char VSPIFACE_001[] = "ISERVERPLUGINCALLBACKS001"; +static const char VSPIFACE_002[] = "ISERVERPLUGINCALLBACKS002"; +static const char GAMEINFO_PATH[] = "|gameinfo_path|"; +IFileSystem *baseFs = NULL; +bool g_bLevelChanged = false; +IServerPluginCallbacks *g_pRealVspCallbacks = NULL; +unsigned int g_vsp_version = 0; + +#define ITER_EVENT(evn, args) \ + CPluginManager::CPlugin *pl; \ + SourceHook::List::iterator event; \ + IMetamodListener *api; \ + for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \ + pl = (*iter); \ + for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \ + api = (*event).event; \ + api->evn args; \ + } \ + } + +/////////////////////////////////// +// Main code for HL2 Interaction // +/////////////////////////////////// + +/* Initialize everything here */ +void InitMainStates() +{ + /* Like Metamod, reload plugins at the end of the map. + * This is so plugins can hook everything on load, BUT, new plugins will be reloaded + * if the server is shut down (silly, but rare case). + */ + bInFirstLevel = true; + + char smm_path[PATH_SIZE]; + const char *game_dir = CommandLine()->ParmValue("-game", "hl2"); + abspath(smm_path, game_dir); + g_ModPath.assign(smm_path); + + SH_ADD_HOOK_STATICFUNC(IServerGameDLL, LevelShutdown, g_GameDll.pGameDLL, LevelShutdown_handler, true); + SH_ADD_HOOK_STATICFUNC(IServerGameDLL, LevelInit, g_GameDll.pGameDLL, LevelInit_handler, true); + SH_ADD_HOOK_STATICFUNC(IServerGameDLL, GameInit, g_GameDll.pGameDLL, GameInit_handler, false); +} + +void DoInitialPluginLoads() +{ + const char *pluginFile = g_Engine.icvar->GetCommandLineValue("mm_pluginsfile"); + const char *mmBaseDir = g_Engine.icvar->GetCommandLineValue("mm_basedir"); + + if (!pluginFile) + { + pluginFile = GetPluginsFile(); + } + if (!mmBaseDir) + { + mmBaseDir = GetMetamodBaseDir(); + } + + char filepath[PATH_SIZE], vdfpath[PATH_SIZE]; + + g_SmmAPI.PathFormat(filepath, sizeof(filepath), "%s/%s", g_ModPath.c_str(), pluginFile); + g_SmmAPI.PathFormat(vdfpath, sizeof(vdfpath), "%s/%s", g_ModPath.c_str(), mmBaseDir); + LoadPlugins(filepath, vdfpath); +} + +bool StartupMetamod(CreateInterfaceFn engineFactory, bool bWaitForGameInit) +{ + g_Engine.engine = (IVEngineServer *)((engineFactory)(INTERFACEVERSION_VENGINESERVER, NULL)); + + if (!g_Engine.engine) + { + Error("Could not find IVEngineServer! Metamod cannot load."); + return false; + } + g_Engine.icvar = (ICvar *)((engineFactory)(VENGINE_CVAR_INTERFACE_VERSION , NULL)); + if (!g_Engine.icvar) + { + Error("Could not find ICvar! Metamod cannot load."); + return false; + } + + g_Engine.loaded = true; + + /* The Ship is the only game known at this time that uses the pre-Episode One engine */ + g_Engine.original = strcmp(CommandLine()->ParmValue("-game", "hl2"), "ship") == 0; + + ConCommandBaseMgr::OneTimeInit(static_cast(&g_SMConVarAccessor)); + + if (g_GameDll.pGameClients) + { + SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, g_GameDll.pGameClients, ClientCommand_handler, false); + } + else + { + /* If IServerGameClients isn't found, this really isn't a fatal error so... */ + LogMessage("[META] Warning: Could not find IServerGameClients!"); + LogMessage("[META] Warning: The 'meta' command will not be available to clients."); + } + + if (!g_SmmAPI.CacheCmds()) + { + LogMessage("[META] Warning: Failed to initialize Con_Printf. Defaulting to Msg()."); + LogMessage("[META] Warning: Console messages will not be redirected to rcon console."); + } + + g_SmmAPI.CacheUserMessages(); + + baseFs = (IFileSystem *)((engineFactory)(FILESYSTEM_INTERFACE_VERSION, NULL)); + if (baseFs == NULL) + { + LogMessage("[META] Failed to find filesystem interface, .vdf files will not be parsed."); + } + + if (!g_SMConVarAccessor.InitConCommandBaseList()) + { + /* This is very unlikely considering it's old engine */ + LogMessage("[META] Warning: Failed to find ConCommandBase list!"); + LogMessage("[META] Warning: ConVars and ConCommands cannot be unregistered properly! Please file a bug report."); + } + + if (!bWaitForGameInit) + { + DoInitialPluginLoads(); + bInFirstLevel = true; + } + + return true; +} + +void LoadAsGameDLL(const gamedll_bridge_info *info) +{ + g_Engine.engineFactory = (CreateInterfaceFn)info->engineFactory; + g_Engine.fileSystemFactory = (CreateInterfaceFn)info->fsFactory; + g_Engine.physicsFactory = (CreateInterfaceFn)info->physicsFactory; + g_Engine.pGlobals = (CGlobalVars*)info->pGlobals; + g_GameDll.loaded = true; + g_GameDll.factory = (CreateInterfaceFn)info->gsFactory; + g_GameDll.pGameDLL = (IServerGameDLL*)info->isgd; + g_GameDllVersion = info->dllVersion; + g_MetamodPath.assign(info->vsp_listener_path); + + InitMainStates(); + + StartupMetamod(g_Engine.engineFactory, false); +} + +bool AlternatelyLoadMetamod(CreateInterfaceFn ifaceFactory, CreateInterfaceFn serverFactory) +{ + g_Engine.engineFactory = ifaceFactory; + g_Engine.fileSystemFactory = ifaceFactory; + g_Engine.physicsFactory = ifaceFactory; + + IPlayerInfoManager *playerInfoManager = (IPlayerInfoManager *)serverFactory("PlayerInfoManager002", NULL); + if (playerInfoManager == NULL) + { + Error("Metamod:Source requires gameinfo.txt modification to load on this game."); + return false; + } + + g_Engine.pGlobals = playerInfoManager->GetGlobalVars(); + + /* Now find the server */ + g_GameDll.factory = serverFactory; + + char gamedll_iface[] = "ServerGameDLL000"; + for (unsigned int i = 3; i <= 50; i++) + { + gamedll_iface[15] = '0' + i; + g_GameDll.pGameDLL = (IServerGameDLL *)serverFactory(gamedll_iface, NULL); + if (g_GameDll.pGameDLL != NULL) + { + g_GameDllVersion = i; + break; + } + } + + if (g_GameDll.pGameDLL == NULL) + { + Error("Metamod:Source requires gameinfo.txt modification to load on this game."); + return false; + } + + char gameclients_iface[] = "ServerGameClients000"; + for (unsigned int i = 3; i <= 4; i++) + { + gameclients_iface[19] = '0' + i; + g_GameDll.pGameClients = (IServerGameClients *)serverFactory(gameclients_iface, NULL); + if (g_GameDll.pGameClients != NULL) + { + break; + } + } + + InitMainStates(); + + if (!StartupMetamod(ifaceFactory, true)) + { + return false; + } + + return true; +} + +bool GameInit_handler() +{ + if (g_bGameInit) + RETURN_META_VALUE(MRES_IGNORED, true); + + if (g_SmmAPI.VSPEnabled() && !g_bIsBridgedAsVsp) + g_SmmAPI.LoadAsVSP(); + + if (g_bIsBridgedAsVsp) + { + DoInitialPluginLoads(); + g_PluginMngr.SetAllLoaded(); + } + + g_bGameInit = true; + + RETURN_META_VALUE(MRES_IGNORED, true); +} + +void UnloadMetamod(bool shutting_down) +{ + /* Unload plugins */ + g_PluginMngr.UnloadAll(); + + if (shutting_down) + { + /* Add the FCVAR_GAMEDLL flag to our cvars so the engine removes them properly */ + g_SMConVarAccessor.MarkCommandsAsGameDLL(); + g_Engine.icvar->UnlinkVariables(FCVAR_GAMEDLL); + } + + g_SourceHook.CompleteShutdown(); +} + +bool LoadFromVDF(const char *file, bool &skipped) +{ + PluginId id; + bool already, kvfileLoaded; + KeyValues *pValues; + const char *plugin_file, *alias; + char full_path[256], error[256]; + + pValues = new KeyValues("Metamod Plugin"); + + if (g_Engine.original) + { + /* The Ship must use a special version of this function */ + kvfileLoaded = KVLoadFromFile(pValues, baseFs, file); + } + else + { + kvfileLoaded = pValues->LoadFromFile(baseFs, file); + } + + if (!kvfileLoaded) + { + pValues->deleteThis(); + skipped = false; + return false; + } + + if ((plugin_file = pValues->GetString("file", NULL)) == NULL) + { + pValues->deleteThis(); + skipped = false; + return false; + } + + if ((alias = pValues->GetString("alias", NULL)) != NULL) + { + g_PluginMngr.SetAlias(alias, plugin_file); + } + + g_SmmAPI.GetFullPluginPath(plugin_file, full_path, sizeof(full_path)); + + id = g_PluginMngr.Load(full_path, Pl_File, already, error, sizeof(error)); + skipped = already; + if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused) + { + LogMessage("[META] Failed to load plugin %s: %s", plugin_file, error); + return false; + } + + pValues->deleteThis(); + return true; +} + +int LoadVDFPluginsFromDir(const char *dir, int &skipped) +{ + bool success, skip; + int total = 0; + char path[MAX_PATH]; + + skipped = 0; + +#if defined _MSC_VER + HANDLE hFind; + WIN32_FIND_DATA fd; + char error[255]; + + g_SmmAPI.PathFormat(path, sizeof(path), "%s\\*.vdf", dir); + if ((hFind = FindFirstFile(path, &fd)) == INVALID_HANDLE_VALUE) + { + DWORD dw = GetLastError(); + if (dw == ERROR_FILE_NOT_FOUND) + return 0; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + error, + sizeof(error), + NULL); + LogMessage("[META] Could not open folder \"%s\" (%s)", dir, error); + return 0; + } + + do + { + g_SmmAPI.PathFormat(path, sizeof(path), "%s\\%s", dir, fd.cFileName); + success = LoadFromVDF(path, skip); + if (skip) + skipped++; + else if (success) + total++; + } while (FindNextFile(hFind, &fd)); + + FindClose(hFind); +#else + DIR *pDir; + struct dirent *pEnt; + int extidx; + + if ((pDir = opendir(dir)) == NULL) + { + LogMessage("[META] Could not open folder \"%s\" (%s)", dir, strerror(errno)); + return 0; + } + + while ((pEnt = readdir(pDir)) != NULL) + { + if (strcmp(pEnt->d_name, ".") == 0 + || strcmp(pEnt->d_name, "..") == 0) + { + continue; + } + extidx = strlen(pEnt->d_name) - 4; + if (extidx < 0 || stricmp(&pEnt->d_name[extidx], ".vdf")) + { + continue; + } + g_SmmAPI.PathFormat(path, sizeof(path), "%s/%s", dir, pEnt->d_name); + success = LoadFromVDF(path, skip); + if (skip) + skipped++; + else if (success) + total++; + } + + closedir(pDir); +#endif + + return total; +} + +bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID) +{ + Assert(filesystem); +#ifdef _MSC_VER + Assert(_heapchk() == _HEAPOK); +#endif + + FileHandle_t f = filesystem->Open(resourceName, "rb", pathID); + if (!f) + return false; + + // load file into a null-terminated buffer + int fileSize = filesystem->Size(f); + char *buffer = (char *)MemAllocScratch(fileSize + 1); + + Assert(buffer); + + filesystem->Read(buffer, fileSize, f); // read into local buffer + + buffer[fileSize] = 0; // null terminate file as EOF + + filesystem->Close( f ); // close file after reading + + bool retOK = kv->LoadFromBuffer( resourceName, buffer, filesystem ); + + MemFreeScratch(); + + return retOK; +} + +int LoadPluginsFromFile(const char *filepath, int &skipped) +{ + FILE *fp; + int total = 0; + PluginId id; + bool already; + + skipped = 0; + + fp = fopen(filepath, "rt"); + if (!fp) + { + return 0; + } + + char buffer[255], error[255], full_path[PATH_SIZE]; + const char *file; + size_t length; + while (!feof(fp) && fgets(buffer, sizeof(buffer), fp) != NULL) + { + UTIL_TrimLeft(buffer); + UTIL_TrimRight(buffer); + + length = strlen(buffer); + if (!length) + { + continue; + } + + if (buffer[0] == '\0' || buffer[0] == ';' || strncmp(buffer, "//", 2) == 0) + { + continue; + } + + file = buffer; + if (buffer[0] == '"') + { + char *cptr = buffer; + file = ++cptr; + + while (*cptr) + { + if (*cptr == '"') + { + *cptr = '\0'; + break; + } + cptr++; + } + } + else + { + char *cptr = buffer; + while (*cptr) + { + if (isspace(*cptr)) + { + char *optr = cptr; + while (*cptr && isspace(*cptr)) + { + cptr++; + } + *optr = '\0'; + UTIL_TrimRight(cptr); + if (*cptr && isalpha(*cptr)) + { + g_PluginMngr.SetAlias(buffer, cptr); + file = cptr; + } + break; + } + cptr++; + } + } + if (!file[0]) + { + continue; + } + g_SmmAPI.GetFullPluginPath(file, full_path, sizeof(full_path)); + id = g_PluginMngr.Load(full_path, Pl_File, already, error, sizeof(error)); + if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused) + { + LogMessage("[META] Failed to load plugin %s. %s", buffer, error); + } + else + { + if (already) + { + skipped++; + } + else + { + total++; + } + } + } + fclose(fp); + + return total; +} + +int LoadPlugins(const char *filepath, const char *vdfpath) +{ + int total, skipped, fskipped, vskipped; + const char *s = ""; + + total = LoadPluginsFromFile(filepath, fskipped); + total += LoadVDFPluginsFromDir(vdfpath, vskipped); + skipped = fskipped + vskipped; + + if (total == 0 || total > 1) + s = "s"; + + if (skipped) + LogMessage("[META] Loaded %d plugin%s (%d already loaded)", total, s, skipped); + else + LogMessage("[META] Loaded %d plugin%s.", total, s); + + return total; +} + +void LogMessage(const char *msg, ...) +{ + va_list ap; + static char buffer[2048]; + + va_start(ap, msg); + size_t len = vsnprintf(buffer, sizeof(buffer) - 2, msg, ap); + va_end(ap); + + buffer[len++] = '\n'; + buffer[len] = '\0'; + + if (!g_Engine.engine) + { + fprintf(stdout, "%s", buffer); + } else { + g_Engine.engine->LogPrint(buffer); + } +} + +void LevelShutdown_handler(void) +{ + if (!bInFirstLevel) + { + char filepath[PATH_SIZE], vdfpath[PATH_SIZE]; + + g_SmmAPI.PathFormat(filepath, sizeof(filepath), "%s/%s", g_ModPath.c_str(), GetPluginsFile()); + g_SmmAPI.PathFormat(vdfpath, sizeof(vdfpath), "%s/%s", g_ModPath.c_str(), GetMetamodBaseDir()); + LoadPlugins(filepath, vdfpath); + } + else + { + bInFirstLevel = false; + } + + g_bLevelChanged = true; + + ITER_EVENT(OnLevelShutdown, ()); + + RETURN_META(MRES_IGNORED); +} + +bool LevelInit_handler(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) +{ + if (!g_SmmAPI.CmdCacheSuccessful()) + { + LogMessage("[META] Warning: Failed to initialize Con_Printf. Defaulting to Msg()."); + LogMessage("[META] Warning: Console messages will not be redirected to rcon console."); + } + + ITER_EVENT(OnLevelInit, (pMapName, pMapEntities, pOldLevel, pLandmarkName, loadGame, background)); + + RETURN_META_VALUE(MRES_IGNORED, false); +} + +#if defined __GNUC__ && (__GNUC__ == 3 || __GNUC__ == 4) +void * operator new(size_t size) { + return(calloc(1, size)); +} + +void * operator new[](size_t size) { + return(calloc(1, size)); +} + +void operator delete(void * ptr) { + if(ptr) + free(ptr); +} + +void operator delete[](void * ptr) { + if(ptr) + free(ptr); +} +#endif diff --git a/utils/mmsource/core-legacy/sourcemm.h b/utils/mmsource/core-legacy/sourcemm.h new file mode 100644 index 00000000..3f587df9 --- /dev/null +++ b/utils/mmsource/core-legacy/sourcemm.h @@ -0,0 +1,119 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2009 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * ============================ + */ + +#ifndef _INCLUDE_SOURCEMM_H +#define _INCLUDE_SOURCEMM_H + +/** + * @brief SourceMM main functionality for GameDLL interception + * @file sourcemm.h + */ + +#include +#include +#include +#include +#include "ISmmAPI.h" +#include "CPlugin.h" +#include "oslink.h" +#include "loader_bridge.h" + +/** + * Versioning + * increase api_major when API breaks + * increase api_minor when new functions are added (non-breaking) + */ +#define SOURCEMM_VERSION SVN_FILE_VERSION_STRING +#define SOURCEMM_DATE __DATE__ +#define SM_VERS_API_MAJOR 1 //increase this on a breaking change +#define SM_VERS_API_MINOR 5 //increase this on a non-breaking API change + +//We need a good CServerGameDLL version to work properly. We support these inclusively. +#define MIN_GAMEDLL_VERSION 3 +#define MAX_GAMEDLL_VERSION 8 + + +void *ServerFactory(const char *name, int *code); +void *EngineFactory(const char *name, int *code); +void *PhysicsFactory(const char *name, int *code); +void *FileSystemFactory(const char *name, int *code); + +/** @brief Loads all plugins found from the mm_pluginsfile file and from VDFs in mm_basedir */ +int LoadPlugins(const char *filepath, const char *vdfdir); + +/** @brief Logs a message to the standard log file */ +void LogMessage(const char *msg, ...); + +/** @brief Stores information about the GameDLL */ +struct GameDllInfo +{ + bool loaded; + CreateInterfaceFn factory; + IServerGameDLL *pGameDLL; + IServerGameClients *pGameClients; +}; + +/** @brief Stores information about the HL2 Engine pointers */ +struct EngineInfo +{ + EngineInfo() : loaded(false), original(false), + engineFactory(NULL), physicsFactory(NULL), fileSystemFactory(NULL), + pGlobals(NULL), icvar(NULL), engine(NULL) + { }; + bool loaded; + bool original; + CreateInterfaceFn engineFactory; + CreateInterfaceFn physicsFactory; + CreateInterfaceFn fileSystemFactory; + CGlobalVars *pGlobals; + ICvar *icvar; + IVEngineServer *engine; +}; + +bool AlternatelyLoadMetamod(CreateInterfaceFn ifaceFactory, CreateInterfaceFn serverFactory); + +extern IServerPluginCallbacks *g_pRealVspCallbacks; +extern bool g_bIsBridgedAsVsp; + +/** @brief Global variable for GameDLL info */ +extern GameDllInfo g_GameDll; + +/** @brief Global variable for Engine info */ +extern EngineInfo g_Engine; + +/** @brief Global singleton for SourceHook */ +extern SourceHook::CSourceHookImpl g_SourceHook; + +/** @brief Mod path (important!)*/ +extern SourceHook::String g_ModPath; + +/** @brief Path to Metamod binary */ +extern SourceHook::String g_MetamodPath; + +/** @brief Global variable for SourceHook macros */ +extern SourceHook::ISourceHook *g_SHPtr; + +/** @brief We have our own internal plugin id... */ +extern PluginId g_PLID; + +/** @brief ServerGameDLL version that is currently loaded */ +extern int g_GameDllVersion; + +extern bool g_bGameInit; +extern bool g_bLevelChanged; + +extern unsigned int g_vsp_version; + +void UnloadMetamod(bool shutting_down); + +void LoadAsGameDLL(const gamedll_bridge_info *info); + +#endif //_INCLUDE_SOURCEMM_H + diff --git a/utils/mmsource/core-legacy/util.cpp b/utils/mmsource/core-legacy/util.cpp new file mode 100644 index 00000000..67f32d62 --- /dev/null +++ b/utils/mmsource/core-legacy/util.cpp @@ -0,0 +1,340 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2008 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * ============================ + */ + +#include +#include +#include +#include "sourcemm.h" +#include "util.h" +#include "oslink.h" + +/** + * @brief Utility functions + * @file util.cpp + */ + +const char *UTIL_GetExtension(const char *file) +{ + int len = strlen(file); + int i = 0; + + for (i = len - 1; i >= 0; i--) + { + if (file[i] == '/' || file[i] == '\\') + { + return NULL; + } + + if ((file[i] == '.') && (i != len - 1)) + { + return (const char *)&(file[i + 1]); + } + } + + return NULL; +} + +void UTIL_TrimLeft(char *buffer) +{ + /* Let's think of this as our iterator */ + char *i = buffer; + + /* Make sure the buffer isn't null */ + if (i && *i) + { + /* Add up number of whitespace characters */ + while(isspace((unsigned char) *i)) + { + i++; + } + + /* If whitespace chars in buffer then adjust string so first non-whitespace char is at start of buffer */ + if (i != buffer) + { + memmove(buffer, i, (strlen(i) + 1) * sizeof(char)); + } + } +} + +void UTIL_TrimRight(char *buffer) +{ + /* Make sure buffer isn't null */ + if (buffer) + { + size_t len = strlen(buffer); + + /* Loop through buffer backwards while replacing whitespace chars with null chars */ + for (size_t i = len - 1; i < len; i--) + { + if (isspace((unsigned char) buffer[i])) + { + buffer[i] = '\0'; + } else { + break; + } + } + } +} + +bool UTIL_PathCmp(const char *path1, const char *path2) +{ + size_t pos1 = 0, pos2 = 0; + + while (true) + { + if (path1[pos1] == '\0' || path2[pos2] == '\0') + { + return (path1[pos1] == path2[pos2]); + } + + if (path1[pos1] == PATH_SEP_CHAR) + { + if (path2[pos2] != PATH_SEP_CHAR) + { + return false; + } + + /* Look for extra path chars */ + while (path1[++pos1]) + { + if (path1[pos1] != PATH_SEP_CHAR) + { + break; + } + } + while (path2[++pos2]) + { + if (path2[pos2] != PATH_SEP_CHAR) + { + break; + } + } + continue; + } + + /* If we're at a different non-alphanumeric, the next character MUST match */ + if (!isalpha(path1[pos1]) && (path1[pos1] != path2[pos2])) + { + return false; + } + + #ifdef WIN32 + if (toupper(path1[pos1]) != toupper(path2[pos2])) + #else + if (path1[pos1] != path2[pos2]) + #endif + { + return false; + } + + pos1++; + pos2++; + } +} + +size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + size_t len = vsnprintf(buffer, maxlength, fmt, ap); + va_end(ap); + + if (len >= maxlength) + { + len = maxlength - 1; + buffer[len] = '\0'; + } + + return len; +} + +inline bool pathchar_isalpha(char a) +{ + return (((a & 1<<7) == 0) && isalpha(a)); +} + +inline bool pathchar_sep(char a) +{ +#if defined WIN32 + return (a == '/' || a == '\\'); +#elif defined __linux__ + return (a == '/'); +#endif +} + +inline bool pathstr_isabsolute(const char *str) +{ +#if defined WIN32 + return (pathchar_isalpha(str[0]) + && str[1] == ':' + && pathchar_sep(str[2])); +#elif defined __linux__ + return (str[0] == '/'); +#endif +} + +inline bool pathchar_cmp(char a, char b) +{ +#if defined WIN32 + if (pathchar_isalpha(a) && pathchar_isalpha(b)) + { + return (tolower(a) == tolower(b)); + } + /* Either path separator is acceptable */ + if (pathchar_sep(a)) + { + return pathchar_sep(b); + } +#endif + return (a == b); +} + +/** + * @brief Forms a relative path given two absolute paths. + * + * @param buffer Buffer to store relative path in. + * @param maxlength Maximum length of the output buffer. + * @param relTo Destination folder to use as a working directory. + * Final folder name should not be pathchar-terminated. + * @param relFrom Source file or folder to use as a target. + * @return True on success, false on failure. + */ +bool UTIL_Relatize(char buffer[], + size_t maxlength, + const char *relTo, + const char *relFrom) +{ + /* We don't allow relative paths in here, force + * the user to resolve these himself! + */ + if (!pathstr_isabsolute(relTo) + || !pathstr_isabsolute(relFrom)) + { + return false; + } + +#if defined WIN32 + /* Relative paths across drives are not possible */ + if (!pathchar_cmp(relTo[0], relFrom[0])) + { + return false; + } + /* Get rid of the drive and semicolon part */ + relTo = &relTo[2]; + relFrom = &relFrom[2]; +#endif + + /* Eliminate the common root between the paths */ + const char *rootTo = NULL; + const char *rootFrom = NULL; + while (*relTo != '\0' && *relFrom != '\0') + { + /* If we get to a new path sequence, start over */ + if (pathchar_sep(*relTo) + && pathchar_sep(*relFrom)) + { + rootTo = relTo; + rootFrom = relFrom; + /* If the paths don't compare, stop looking for a common root */ + } else if (!pathchar_cmp(*relTo, *relFrom)) { + break; + } + relTo++; + relFrom++; + } + + /* NULLs shouldn't happen! */ + if (rootTo == NULL + || rootFrom == NULL) + { + return false; + } + + size_t numLevels = 0; + + /* The root case is special! + * Don't count anything from it. + */ + if (*(rootTo + 1) != '\0') + { + /* Search for how many levels we need to go up. + * Since the root pointer points to a '/', we increment + * the initial pointer by one. + */ + while (*rootTo != '\0') + { + if (pathchar_sep(*rootTo)) + { + /* Check for an improper trailing slash, + * just to be nice even though the user + * should NOT have done this! + */ + if (*(rootTo + 1) == '\0') + { + break; + } + numLevels++; + } + rootTo++; + } + } + + /* Now build the new relative path. */ + size_t len, total = 0; + while (numLevels--) + { + len = _snprintf(&buffer[total], maxlength - total, ".." PATH_SEP_STR); + if (len >= maxlength - total) + { + /* Not enough space in the buffer */ + return false; + } + total += len; + } + + /* Add the absolute path. */ + len = _snprintf(&buffer[total], maxlength - total, "%s", &rootFrom[1]); + if (len >= maxlength - total) + { + return false; + } + + return true; +} + +size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params) +{ + size_t len = vsnprintf(buffer, maxlength, fmt, params); + + if (len >= maxlength) + { + len = maxlength - 1; + buffer[len] = '\0'; + } + + return len; +} + +bool UTIL_VerifySignature(const void *addr, const char *sig, size_t len) +{ + unsigned char *addr1 = (unsigned char *) addr; + unsigned char *addr2 = (unsigned char *) sig; + + for (size_t i = 0; i < len; i++) + { + if (addr2[i] == '*') + continue; + if (addr1[i] != addr2[i]) + return false; + } + + return true; +} diff --git a/utils/mmsource/core-legacy/util.h b/utils/mmsource/core-legacy/util.h new file mode 100644 index 00000000..6ee9bc9e --- /dev/null +++ b/utils/mmsource/core-legacy/util.h @@ -0,0 +1,109 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2008 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * ============================ + */ + +#ifndef _INCLUDE_UTIL_H +#define _INCLUDE_UTIL_H + +#include +#include "sourcehook/sourcehook.h" + +/** + * @brief Utility functions + * @file util.h + */ + +#define IA32_JMP_IMM32 '\xE9' + +/** + * @brief Returns a pointer to the extension in a file name. + */ +const char *UTIL_GetExtension(const char *file); + +/** + * @brief Removes whitespace characters from left side of string. + */ +void UTIL_TrimLeft(char *buffer); + +/** + * @brief Removes whitespace characters from right side of string. + */ +void UTIL_TrimRight(char *buffer); + +/** + * @brief Compares two file paths. + */ +bool UTIL_PathCmp(const char *path1, const char *path2); + +/** + * @brief Same as snprintf except that it ensures the string buffer is null terminated. + */ +size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...); + +/** + * @brief Same as vsnprintf except that it ensures the string buffer is null terminated. + */ +size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params); + +/** + * @brief Forms a relative path given two absolute paths. + * + * @param buffer Buffer to store relative path in. + * @param maxlength Maximum length of the output buffer. + * @param relTo Destination folder to use as a working directory. + * Final folder name should not be pathchar-terminated. + * @param relFrom Source file or folder to use as a target. + * @return True on success, false on failure. + */ +bool UTIL_Relatize(char buffer[], + size_t maxlength, + const char *relTo, + const char *relFrom); + +/** + * @brief Compares memory address against a signature. + * + * @param addr Memory address to check. + * @param sig Signature used to check against memory address. Accept 0x2A as wildcard. + * @param len Length of signature. + * @return True if signature was verified, false otherwise. + */ +bool UTIL_VerifySignature(const void *addr, const char *sig, size_t len); + +/** + * @brief Returns the original function address of a given virtual function. + * + * @param mfp Member function pointer to virtual function. + * @param ptr Pointer to interface in which the virtual function belongs. + * @return Address of function originally pointed to by the virtual function. + */ +template +char *UTIL_GetOrigFunction(MFP vfunc, Iface *ptr) +{ + SourceHook::MemFuncInfo info = {true, -1, 0, 0}; + SourceHook::GetFuncInfo(vfunc, info); + + /* Get address of original GetUserMessageInfo() */ + char *func = reinterpret_cast(SH_GET_ORIG_VFNPTR_ENTRY(ptr, vfunc)); + + /* Check for relative jumps */ + if (func[0] == IA32_JMP_IMM32) + { + /* Get address from displacement... + * + * Add 5 because it's relative to next instruction: + * Opcode <1 byte> + 32-bit displacement <4 bytes> + */ + func += *reinterpret_cast(func + 1) + 5; + } + + return func; +} + +#endif //_INCLUDE_UTIL_H diff --git a/utils/mmsource/core-legacy/version.rc b/utils/mmsource/core-legacy/version.rc new file mode 100644 index 00000000..ce93a169 --- /dev/null +++ b/utils/mmsource/core-legacy/version.rc @@ -0,0 +1,102 @@ +// Microsoft Visual C++ generated resource script. +// + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" +#include + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION MMS_FILE_VERSION + PRODUCTVERSION MMS_FILE_VERSION + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Comments", "Metamod: Source" + VALUE "FileDescription", "Metamod: Source" + VALUE "FileVersion", MMS_FULL_VERSION + VALUE "InternalName", "mmsource" + VALUE "LegalCopyright", "Copyright (c) 2004-2010, Metamod: Source Development Team" + VALUE "OriginalFilename", BINARY_NAME + VALUE "ProductName", "Metamod:Source" + VALUE "ProductVersion", MMS_FULL_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/utils/mmsource/core-legacy/vsp_bridge.cpp b/utils/mmsource/core-legacy/vsp_bridge.cpp new file mode 100644 index 00000000..17172e27 --- /dev/null +++ b/utils/mmsource/core-legacy/vsp_bridge.cpp @@ -0,0 +1,138 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ====================================================== + * Metamod:Source + * Copyright (C) 2004-2009 AlliedModders LLC and authors. + * All rights reserved. + * ====================================================== + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in a + * product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#include +#include "sourcemm.h" +#include "concommands.h" +#include "util.h" +#include +#include +#include + +SH_DECL_HOOK0_void(ConCommand, Dispatch, SH_NOATTRIB, false); + +ConCommand *g_plugin_unload = NULL; +bool g_bIsTryingToUnload; +bool g_bIsBridgedAsVsp; +SourceHook::String vsp_desc("Metamod:Source"); + +void InterceptPluginUnloads() +{ + g_bIsTryingToUnload = true; +} + +void InterceptPluginUnloads_Post() +{ + g_bIsTryingToUnload = false; +} + +class VspBridge : public IVspBridge +{ + virtual bool Load(const vsp_bridge_info *info, char *error, size_t maxlength) + { + assert(!g_bIsBridgedAsVsp); + + if (!g_GameDll.loaded) + { + vsp_desc.append(" "); + vsp_desc.append(METAMOD_VERSION); + + CreateInterfaceFn engineFactory = (CreateInterfaceFn)info->engineFactory; + CreateInterfaceFn gsFactory = (CreateInterfaceFn)info->gsFactory; + + if (!AlternatelyLoadMetamod(engineFactory, gsFactory)) + return false; + + extern ConVar metamod_version; + char buffer[255]; + + UTIL_Format(buffer, sizeof(buffer), "%sV", metamod_version.GetString()); + metamod_version.SetValue(buffer); + } + else + { + vsp_desc.append(" Interface "); + vsp_desc.append(METAMOD_VERSION); + } + + ConCommandBase *pBase = g_Engine.icvar->GetCommands(); + while (pBase != NULL) + { + if (pBase->IsCommand() && strcmp(pBase->GetName(), "plugin_unload") == 0) + { + g_plugin_unload = (ConCommand *)pBase; + break; + } + pBase = const_cast(pBase->GetNext()); + } + + if (g_plugin_unload != NULL) + { + SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads, false); + SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads_Post, true); + } + + g_bIsBridgedAsVsp = true; + g_pRealVspCallbacks = info->vsp_callbacks; + g_vsp_version = info->vsp_version; + + g_PluginMngr.SetVSPAsLoaded(); + + return true; + } + + virtual void Unload() + { + if (g_bIsTryingToUnload) + { + Error("Metamod:Source cannot be unloaded from VSP mode. Use \"meta unload\" to unload specific plugins.\n"); + return; + } + if (g_plugin_unload != NULL) + { + SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads, false); + SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads_Post, true); + g_plugin_unload = NULL; + } + if (!g_GameDll.loaded) + { + g_SMConVarAccessor.UnloadMetamodCommands(); + UnloadMetamod(false); + } + } + + virtual const char *GetDescription() + { + return vsp_desc.c_str(); + } +}; + +VspBridge mm14_vsp_bridge; + +SMM_API IVspBridge * +GetVspBridge() +{ + return &mm14_vsp_bridge; +} diff --git a/utils/mmsource/core/AMBuilder b/utils/mmsource/core/AMBuilder index f583482c..5b158872 100644 --- a/utils/mmsource/core/AMBuilder +++ b/utils/mmsource/core/AMBuilder @@ -2,34 +2,29 @@ import os for sdk_name in MMS.sdks: - for arch in MMS.archs: - sdk = MMS.sdks[sdk_name] + sdk = MMS.sdks[sdk_name] + if sdk.name == 'episode1': + continue - if not arch in sdk.platformSpec[builder.target.platform]: - continue + name = 'metamod.' + sdk.ext + binary = MMS.HL2Library(builder, name, sdk) - name = 'metamod.' + sdk.ext - binary = MMS.HL2Library(builder, name, sdk, arch) - - binary.sources += [ - 'metamod.cpp', - 'metamod_console.cpp', - 'metamod_oslink.cpp', - 'metamod_plugins.cpp', - 'metamod_util.cpp', - 'provider/console.cpp', - 'provider/provider_ep2.cpp', - 'sourcehook/sourcehook.cpp', - 'sourcehook/sourcehook_impl_chookidman.cpp', - 'sourcehook/sourcehook_impl_chookmaninfo.cpp', - 'sourcehook/sourcehook_impl_cproto.cpp', - 'sourcehook/sourcehook_impl_cvfnptr.cpp', - 'gamedll_bridge.cpp', - 'vsp_bridge.cpp' - ] - - # Source2 hack. TODO: check this more deterministically, "are we doing an x64 build?" - if arch == 'x86': - binary.sources += ['sourcehook/sourcehook_hookmangen.cpp'] - nodes = builder.Add(binary) - MMS.binaries += [nodes] + binary.sources += [ + 'metamod.cpp', + 'metamod_console.cpp', + 'metamod_oslink.cpp', + 'metamod_plugins.cpp', + 'metamod_util.cpp', + 'provider/console.cpp', + 'provider/provider_ep2.cpp', + 'sourcehook/sourcehook.cpp', + 'sourcehook/sourcehook_hookmangen.cpp', + 'sourcehook/sourcehook_impl_chookidman.cpp', + 'sourcehook/sourcehook_impl_chookmaninfo.cpp', + 'sourcehook/sourcehook_impl_cproto.cpp', + 'sourcehook/sourcehook_impl_cvfnptr.cpp', + 'gamedll_bridge.cpp', + 'vsp_bridge.cpp' + ] + nodes = builder.Add(binary) + MMS.binaries += [nodes] diff --git a/utils/mmsource/core/ISmmAPI.h b/utils/mmsource/core/ISmmAPI.h index 0788e08f..65a01fd9 100644 --- a/utils/mmsource/core/ISmmAPI.h +++ b/utils/mmsource/core/ISmmAPI.h @@ -39,6 +39,7 @@ #if defined META_NO_HL2SDK class CGlobalVars; +class IServerPluginCallbacks; struct edict_t; class ConCommandBase; #else @@ -48,6 +49,12 @@ class ConCommandBase; #include #include +#if defined __GNUC__ +#if ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)) || (__GNUC__ < 3) +#error "You must compile with at least GCC 3.4! If you know what you are doing, you can remove this message." +#endif //version check +#endif //__GNUC__ + #define MMIFACE_SOURCEHOOK "ISourceHook" /**< ISourceHook Pointer */ #define MMIFACE_PLMANAGER "IPluginManager" /**< SourceMM Plugin Functions */ #define MMIFACE_SH_HOOKMANAUTOGEN "IHookManagerAutoGen" /**< SourceHook::IHookManagerAutoGen Pointer */ @@ -55,8 +62,6 @@ class ConCommandBase; typedef void* (*CreateInterfaceFn)(const char *pName, int *pReturnCode); -class IServerPluginCallbacks; - namespace SourceMM { class ISmmPlugin; diff --git a/utils/mmsource/core/ISmmPlugin.h b/utils/mmsource/core/ISmmPlugin.h index d15dfc54..7b9f0ac2 100644 --- a/utils/mmsource/core/ISmmPlugin.h +++ b/utils/mmsource/core/ISmmPlugin.h @@ -40,14 +40,8 @@ #include #ifndef META_NO_HL2SDK -#if SOURCE_ENGINE == SE_DOTA -#include -#else #include #endif -#endif - -class IServerPluginCallbacks; // Interface return status, binary-compatible with HL2SDK's IFACE_OK and IFACE_FAILED. enum @@ -506,7 +500,11 @@ using namespace SourceMM; #if defined __WIN32__ || defined _WIN32 || defined WIN32 #define SMM_API extern "C" __declspec(dllexport) #elif defined __GNUC__ - #define SMM_API extern "C" __attribute__ ((visibility("default"))) + #if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 1) + #define SMM_API extern "C" __attribute__ ((visibility("default"))) + #else + #define SMM_API extern "C" + #endif #endif #endif //!defined SMM_API diff --git a/utils/mmsource/core/ISmmPluginExt.h b/utils/mmsource/core/ISmmPluginExt.h index 351b9065..9b313b62 100644 --- a/utils/mmsource/core/ISmmPluginExt.h +++ b/utils/mmsource/core/ISmmPluginExt.h @@ -61,7 +61,7 @@ #define SOURCE_ENGINE_BMS 23 /**< Black Mesa Multiplayer */ #define SOURCE_ENGINE_DOI 24 /**< Day of Infamy */ -#define METAMOD_PLAPI_VERSION 16 /**< Version of this header file */ +#define METAMOD_PLAPI_VERSION 15 /**< Version of this header file */ #define METAMOD_PLAPI_NAME "ISmmPlugin" /**< Name of the plugin interface */ namespace SourceMM diff --git a/utils/mmsource/core/gamedll_bridge.cpp b/utils/mmsource/core/gamedll_bridge.cpp index 9c8c34b1..21d730f0 100644 --- a/utils/mmsource/core/gamedll_bridge.cpp +++ b/utils/mmsource/core/gamedll_bridge.cpp @@ -63,11 +63,7 @@ class GameDllBridge : public IGameDllBridge SourceHook::MemFuncInfo mfi; mfi.isVirtual = false; -#if SOURCE_ENGINE == SE_DOTA - SourceHook::GetFuncInfo(&IServerGameDLL::Shutdown, mfi); -#else SourceHook::GetFuncInfo(&IServerGameDLL::DLLShutdown, mfi); -#endif assert(mfi.isVirtual); assert(mfi.vtbloffs == 0); assert(mfi.thisptroffs == 0); diff --git a/utils/mmsource/core/metamod.cpp b/utils/mmsource/core/metamod.cpp index 4ef99889..2dbe233a 100644 --- a/utils/mmsource/core/metamod.cpp +++ b/utils/mmsource/core/metamod.cpp @@ -28,24 +28,14 @@ #include "metamod.h" #include #include -#include +#include #include "metamod_provider.h" #include "metamod_plugins.h" #include "metamod_util.h" #include "metamod_console.h" #include "provider/provider_ep2.h" +#if defined __linux__ #include -#if SOURCE_ENGINE == SE_DOTA -#include -#endif - -#define X64_SUFFIX ".x64" -#if defined(WIN32) || defined(_WIN32) -#define BINARY_EXT ".dll" -#elif defined(__linux__) -#define BINARY_EXT ".so" -#elif defined(__APPLE__) -#define BINARY_EXT ".dylib" #endif using namespace SourceMM; @@ -57,28 +47,6 @@ using namespace SourceHook::Impl; * @file sourcemm.cpp */ -#if SOURCE_ENGINE == SE_DOTA -// Hack to make hook decl compile when only having forward decl in header. -// (we have class structure but it requires protobuf which we don't want to include here) -class GameSessionConfiguration_t { }; - -SH_DECL_MANUALHOOK3_void(SGD_StartupServer, 0, 0, 0, const GameSessionConfiguration_t &, ISource2WorldSession *, const char *); -SH_DECL_MANUALHOOK2_void(SGD_Init, 0, 0, 0, GameSessionConfiguration_t *, const char *); -SH_DECL_MANUALHOOK3(SGD_StartChangeLevel, 0, 0, 0, CUtlVector *, const char *, const char *, void *); -SH_DECL_MANUALHOOK5_void(SGD_SwitchToLoop, 0, 0, 0, const char *, KeyValues *, uint32, const char *, bool); - -static void -Handler_SwitchToLoop(const char *, KeyValues *, uint32, const char *, bool); - -static void -Handler_StartupServer_Post(const GameSessionConfiguration_t &, ISource2WorldSession *, const char *); - -static void -Handler_Init(GameSessionConfiguration_t *, const char *); - -static CUtlVector * -Handler_StartChangeLevel(const char *, const char *, void *); -#else SH_DECL_MANUALHOOK0(SGD_GameInit, 0, 0, 0, bool); SH_DECL_MANUALHOOK6(SGD_LevelInit, 0, 0, 0, bool, const char *, const char *, const char *, const char *, bool, bool); SH_DECL_MANUALHOOK0_void(SGD_LevelShutdown, 0, 0, 0); @@ -96,7 +64,6 @@ Handler_LevelInit(char const *pMapName, static bool Handler_GameInit(); -#endif static void InitializeVSP(); @@ -131,9 +98,8 @@ static ConVar *mm_basedir = NULL; static CreateInterfaceFn engine_factory = NULL; static CreateInterfaceFn physics_factory = NULL; static CreateInterfaceFn filesystem_factory = NULL; -#if !defined( _WIN64 ) && !defined( __amd64__ ) +static CGlobalVars *gpGlobals = NULL; static CHookManagerAutoGen g_SH_HookManagerAutoGen(&g_SourceHook); -#endif static META_RES last_meta_res; static IServerPluginCallbacks *vsp_callbacks = NULL; static bool were_plugins_loaded = false; @@ -156,7 +122,7 @@ SourceMM::ISmmAPI *g_pMetamod = &g_Metamod; pl = (*iter); \ for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \ api = (*event); \ - mret = META_IFACE_FAILED; \ + mret = IFACE_FAILED; \ if ( (val=api->On##nam##Query(iface, &mret)) != NULL ) { \ if (ret) *ret = mret; \ return val; \ @@ -191,23 +157,6 @@ mm_InitializeForLoad() */ in_first_level = true; -#if SOURCE_ENGINE == SE_DOTA - SourceHook::MemFuncInfo info; - - if (!provider->GetHookInfo(ProvidedHook_StartupServer, &info)) - { - provider->DisplayError("Metamod:Source could not find a valid hook for INetworkServerService::StartupServer"); - } - SH_MANUALHOOK_RECONFIGURE(SGD_StartupServer, info.vtblindex, info.vtbloffs, info.thisptroffs); - SH_ADD_MANUALHOOK(SGD_StartupServer, netservice, SH_STATIC(Handler_StartupServer_Post), true); - - if (!provider->GetHookInfo(ProvidedHook_SwitchToLoop, &info)) - { - provider->DisplayError("Metamod:Source could not find a valid hook for IEngineServiceMgr::SwitchToLoop"); - } - SH_MANUALHOOK_RECONFIGURE(SGD_SwitchToLoop, info.vtblindex, info.vtbloffs, info.thisptroffs); - SH_ADD_MANUALHOOK(SGD_SwitchToLoop, enginesvcmgr, SH_STATIC(Handler_SwitchToLoop), false); -#else SourceHook::MemFuncInfo info; if (!provider->GetHookInfo(ProvidedHook_GameInit, &info)) @@ -230,7 +179,6 @@ mm_InitializeForLoad() } SH_MANUALHOOK_RECONFIGURE(SGD_LevelShutdown, info.vtblindex, info.vtbloffs, info.thisptroffs); SH_ADD_MANUALHOOK_STATICFUNC(SGD_LevelShutdown, server, Handler_LevelShutdown, true); -#endif } bool @@ -375,13 +323,7 @@ void InitializeVSP() break; } } - - /* If this fails the file either does not exist or - * on Windows the buffer may be too small. */ - if (abspath(engine_path, engine_file) == NULL) - { - engine_path[0] = '\0'; - } + abspath(engine_path, engine_file); const char *usepath = metamod_path.c_str(); if (UTIL_Relatize(rel_path, sizeof(rel_path), engine_path, metamod_path.c_str())) @@ -527,26 +469,11 @@ mm_InitializeGlobals(CreateInterfaceFn engineFactory, provider->Notify_DLLInit_Pre(engineFactory, gamedll_info.factory); } -void -mm_UnloadMetamod() -{ - /* Unload plugins */ - g_PluginMngr.UnloadAll(); - - provider->Notify_DLLShutdown_Pre(); - - g_SourceHook.CompleteShutdown(); -} - -static void -mm_HandleGameInit() +static bool +Handler_GameInit() { if (is_game_init) - return; - -#if SOURCE_ENGINE == SE_DOTA - DevMsg("MMS: GameInit\n"); -#endif + return true; if (vsp_load_requested) InitializeVSP(); @@ -559,15 +486,24 @@ mm_HandleGameInit() } is_game_init = true; + + RETURN_META_VALUE(MRES_IGNORED, true); } -static void -mm_HandleLevelShutdown() +void +mm_UnloadMetamod() { -#if SOURCE_ENGINE == SE_DOTA - DevMsg("MMS: LevelShutdown\n"); -#endif + /* Unload plugins */ + g_PluginMngr.UnloadAll(); + + provider->Notify_DLLShutdown_Pre(); + + g_SourceHook.CompleteShutdown(); +} +static void +Handler_LevelShutdown(void) +{ if (g_bIsVspBridged && !were_plugins_loaded) { DoInitialPluginLoads(); @@ -598,96 +534,6 @@ mm_HandleLevelShutdown() } ITER_EVENT(OnLevelShutdown, ()); -} - -static void -mm_HandleLevelInit(char const *pMapName, -char const *pMapEntities, -char const *pOldLevel, -char const *pLandmarkName, -bool loadGame, -bool background) -{ -#if SOURCE_ENGINE == SE_DOTA - DevMsg("MMS: LevelInit\n"); -#endif - - ITER_EVENT(OnLevelInit, (pMapName, pMapEntities, pOldLevel, pLandmarkName, loadGame, background)); -} -#include -#if SOURCE_ENGINE == SE_DOTA -static void -Handler_SwitchToLoop(const char *pszLoopName, KeyValues *pKV, uint32 nId, const char *pszUnk, bool bUnk) -{ - if (strcmp(pszLoopName, "levelload") == 0) - { - mm_HandleGameInit(); - } - - RETURN_META(MRES_IGNORED); -} - -static void -Handler_StartupServer_Post(const GameSessionConfiguration_t &config, ISource2WorldSession *, const char *) -{ - static bool bGameServerHooked = false; - if (!bGameServerHooked) - { - INetworkGameServer *netserver = (META_IFACEPTR(INetworkServerService))->GetIGameServer(); - - SourceHook::MemFuncInfo info; - if (!provider->GetHookInfo(ProvidedHook_Init, &info)) - { - provider->DisplayError("Metamod:Source could not find a valid hook for INetworkGameServer::Init"); - } - SH_MANUALHOOK_RECONFIGURE(SGD_Init, info.vtblindex, info.vtbloffs, info.thisptroffs); - SH_ADD_MANUALVPHOOK(SGD_Init, netserver, SH_STATIC(Handler_Init), false); - - if (!provider->GetHookInfo(ProvidedHook_StartChangeLevel, &info)) - { - provider->DisplayError("Metamod:Source could not find a valid hook for INetworkGameServer::StartChangeLevel"); - } - SH_MANUALHOOK_RECONFIGURE(SGD_StartChangeLevel, info.vtblindex, info.vtbloffs, info.thisptroffs); - SH_ADD_MANUALVPHOOK(SGD_StartChangeLevel, netserver, SH_STATIC(Handler_StartChangeLevel), false); - - bGameServerHooked = true; - } - - RETURN_META(MRES_IGNORED); -} - -static void -Handler_Init(GameSessionConfiguration_t *pConfig, const char *pszMapName) -{ - static char szLastMap[260] = ""; - mm_HandleLevelInit(pszMapName, "", szLastMap, "", false, false); - UTIL_Format(szLastMap, sizeof(szLastMap), "%s", pszMapName); - - RETURN_META(MRES_IGNORED); -} - -static CUtlVector * -Handler_StartChangeLevel(const char *, const char *, void *) -{ - mm_HandleLevelShutdown(); - - RETURN_META_VALUE(MRES_IGNORED, nullptr); -} - -#else - -static bool -Handler_GameInit() -{ - mm_HandleGameInit(); - - RETURN_META_VALUE(MRES_IGNORED, true); -} - -static void -Handler_LevelShutdown(void) -{ - mm_HandleLevelShutdown(); RETURN_META(MRES_IGNORED); } @@ -704,7 +550,6 @@ Handler_LevelInit(char const *pMapName, RETURN_META_VALUE(MRES_IGNORED, false); } -#endif void MetamodSource::LogMsg(ISmmPlugin *pl, const char *msg, ...) { @@ -843,7 +688,7 @@ void *MetamodSource::InterfaceSearch(CreateInterfaceFn fn, const char *iface, in { if (ret) { - *ret = META_IFACE_FAILED; + *ret = IFACE_FAILED; } return NULL; } @@ -996,7 +841,7 @@ void *MetamodSource::MetaFactory(const char *iface, int *ret, PluginId *id) { if (ret) { - *ret = META_IFACE_OK; + *ret = IFACE_OK; } return static_cast(static_cast(&g_SourceHook)); } @@ -1004,25 +849,17 @@ void *MetamodSource::MetaFactory(const char *iface, int *ret, PluginId *id) { if (ret) { - *ret = META_IFACE_OK; + *ret = IFACE_OK; } return static_cast(static_cast(&g_PluginMngr)); } else if (strcmp(iface, MMIFACE_SH_HOOKMANAUTOGEN) == 0) { -#if defined( _WIN64 ) || defined( __amd64__ ) - if (ret) - { - *ret = META_IFACE_FAILED; - } - return nullptr; -#else if (ret) { - *ret = META_IFACE_OK; + *ret = IFACE_OK; } return static_cast(static_cast(&g_SH_HookManagerAutoGen)); -#endif } CPluginManager::CPlugin *pl; @@ -1039,7 +876,7 @@ void *MetamodSource::MetaFactory(const char *iface, int *ret, PluginId *id) for (event = pl->m_Events.begin(); event != pl->m_Events.end(); event++) { api = (*event); - subret = META_IFACE_FAILED; + subret = IFACE_FAILED; if ((value = api->OnMetamodQuery(iface, &subret)) != NULL) { if (ret) @@ -1057,7 +894,7 @@ void *MetamodSource::MetaFactory(const char *iface, int *ret, PluginId *id) if (ret) { - *ret = META_IFACE_FAILED; + *ret = IFACE_FAILED; } return NULL; @@ -1248,24 +1085,12 @@ size_t MetamodSource::GetFullPluginPath(const char *plugin, char *buffer, size_t /* Add an extension if there's none there */ if (!pext) { -#if defined(WIN32) || defined(_WIN32) -#if defined(WIN64) || defined(_WIN64) - ext = X64_SUFFIX BINARY_EXT; -#else - ext = BINARY_EXT; -#endif +#if defined WIN32 || defined _WIN32 + ext = ".dll"; #elif defined __APPLE__ -#if defined (__x86_64__) - ext = X64_SUFFIX BINARY_EXT; + ext = ".dylib"; #else - ext = BINARY_EXT; -#endif -#else -#if defined(__x86_64__) - ext = X64_SUFFIX BINARY_EXT; -#else - ext = "_i486" BINARY_EXT; -#endif + ext = "_i486.so"; #endif } else @@ -1276,12 +1101,12 @@ size_t MetamodSource::GetFullPluginPath(const char *plugin, char *buffer, size_t /* Format the new path */ num = PathFormat(buffer, len, "%s/%s%s", mod_path.c_str(), plugin, ext); - /* If path was passed without extension and it doesn't exist with "." try "." */ -#if defined(WIN64) || defined (_WIN64) || defined(__linux__) || defined(__x86_64__) +#if defined __linux__ + /* If path was passed without extension and it doesn't exist with "_i486.so" try ".so" */ struct stat s; if (!pext && stat(buffer, &s) != 0) { - num = PathFormat(buffer, len, "%s/%s" BINARY_EXT, mod_path.c_str(), plugin); + num = PathFormat(buffer, len, "%s/%s.so", mod_path.c_str(), plugin); } #endif diff --git a/utils/mmsource/core/metamod_console.cpp b/utils/mmsource/core/metamod_console.cpp index 7804b49f..fc4e26ab 100644 --- a/utils/mmsource/core/metamod_console.cpp +++ b/utils/mmsource/core/metamod_console.cpp @@ -26,7 +26,7 @@ #include #include "metamod_oslink.h" #include -#include +#include #include "metamod.h" #include "metamod_util.h" #include "metamod_console.h" @@ -42,63 +42,6 @@ using namespace SourceHook; #define CONMSG g_Metamod.ConPrintf #define CLIENT_CONMSG g_Metamod.ClientConPrintf -template - -#if SOURCE_ENGINE == SE_DOTA -void CMDMSG(int client, const char *pMsg, Ts ... ts) -#else -void CMDMSG(edict_t *client, const char *pMsg, Ts ... ts) -#endif -{ - if (client) - { - CLIENT_CONMSG(client, pMsg, ts...); - } - else - { - CONMSG(pMsg, ts...); - } -} - -#if SOURCE_ENGINE == SE_DOTA -static void ReplyCredits(int client = 0) -#else -static void ReplyCredits(edict_t *client = nullptr) -#endif -{ - CMDMSG(client, "Metamod:Source was developed by:\n"); - CMDMSG(client, " SourceHook: Pavol \"PM OnoTo\" Marko\n"); - CMDMSG(client, " GameDLL/Plugins: David \"BAILOPAN\" Anderson\n"); - CMDMSG(client, " GameDLL: Scott \"DS\" Ehlert\n"); - CMDMSG(client, "For more information, see the official website\n"); - CMDMSG(client, "http://www.metamodsource.net/\n"); -} - -#if SOURCE_ENGINE == SE_DOTA -static void ReplyVersion(int client = 0) -#else -static void ReplyVersion(edict_t *client = nullptr) -#endif -{ - CMDMSG(client, " Metamod:Source Version Information\n"); - CMDMSG(client, " Metamod:Source version %s\n", METAMOD_VERSION); - CMDMSG(client, " Plugin interface version: %d:%d\n", METAMOD_PLAPI_VERSION, PLAPI_MIN_VERSION); - CMDMSG(client, " SourceHook version: %d:%d\n", g_SHPtr->GetIfaceVersion(), g_SHPtr->GetImplVersion()); - if (g_Metamod.IsLoadedAsGameDLL()) - { - CMDMSG(client, " Loaded As: GameDLL (gameinfo.txt)\n"); - } - else - { - CMDMSG(client, " Loaded As: Valve Server Plugin\n"); - } - CMDMSG(client, " Compiled on: %s\n", MMS_BUILD_TIMESTAMP); -#if defined(MMS_GENERATED_BUILD) - CMDMSG(client, " Built from: https://github.com/alliedmodders/metamod-source/commit/%s\n", METAMOD_SHA); - CMDMSG(client, " Build ID: %s:%s\n", METAMOD_LOCAL_REV, METAMOD_SHA); -#endif - CMDMSG(client, " http://www.metamodsource.net/\n"); -} bool Command_Meta(IMetamodSourceCommandInfo *info) { @@ -115,13 +58,36 @@ bool Command_Meta(IMetamodSourceCommandInfo *info) const char *command = info->GetArg(1); if (strcmp(command, "credits") == 0) { - ReplyCredits(); + CONMSG("Metamod:Source was developed by:\n"); + CONMSG(" SourceHook: Pavol \"PM OnoTo\" Marko\n"); + CONMSG(" GameDLL/Plugins: David \"BAILOPAN\" Anderson\n"); + CONMSG(" GameDLL: Scott \"DS\" Ehlert\n"); + CONMSG("For more information, see the official website\n"); + CONMSG("http://www.metamodsource.net/\n"); return true; } else if (strcmp(command, "version") == 0) { - ReplyVersion(); + CONMSG("Metamod:Source version %s\n", METAMOD_VERSION); +#if defined(MMS_GENERATED_BUILD) + CONMSG("Built from: https://github.com/alliedmodders/metamod-source/commit/%s\n", METAMOD_BUILD_SHA); +#endif + CONMSG("Build ID: %s:%s\n", METAMOD_BUILD_LOCAL_REV, METAMOD_BUILD_SHA); + + if (g_Metamod.IsLoadedAsGameDLL()) + { + CONMSG("Loaded As: GameDLL (gameinfo.txt)\n"); + } + else + { + CONMSG("Loaded As: Valve Server Plugin\n"); + } + + CONMSG("Compiled on: %s\n", SOURCEMM_DATE); + CONMSG("Plugin interface version: %d:%d\n", METAMOD_PLAPI_VERSION, PLAPI_MIN_VERSION); + CONMSG("SourceHook version: %d:%d\n", g_SHPtr->GetIfaceVersion(), g_SHPtr->GetImplVersion()); + CONMSG("http://www.metamodsource.net/\n"); return true; } @@ -132,7 +98,68 @@ bool Command_Meta(IMetamodSourceCommandInfo *info) CONMSG(" Mod Path: %s\n", g_Metamod.GetBaseDir()); CONMSG(" DLL Path: %s\n", g_Metamod.GetGameBinaryPath()); CONMSG(" Interface: ServerGameDLL%03d\n", g_Metamod.GetGameDLLVersion()); - CONMSG(" Engine: %s\n", provider->GetEngineDescription()); + +#if 0 + int engine = g_Metamod.GetSourceEngineBuild(); + if (engine == SOURCE_ENGINE_ORIGINAL) + { + CONMSG(" Engine: Original (pre-Episode 1)\n"); + } + else if (engine == SOURCE_ENGINE_EPISODEONE) + { + CONMSG(" Engine: Episode 1 (2004)\n"); + } + else if (engine == SOURCE_ENGINE_ORANGEBOX) + { + CONMSG(" Engine: Episode 2 (Orange Box, 2007)\n"); + } +#endif + +#if SOURCE_ENGINE == SE_BLOODYGOODTIME + CONMSG(" Engine: Bloody Good Time (2010)\n"); +#elif SOURCE_ENGINE == SE_ALIENSWARM + CONMSG(" Engine: Alien Swarm (2010)\n"); +#elif SOURCE_ENGINE == SE_LEFT4DEAD2 + CONMSG(" Engine: Left 4 Dead 2 (2009)\n"); +#elif SOURCE_ENGINE == SE_NUCLEARDAWN + CONMSG(" Engine: Nuclear Dawn (2011)\n"); +#elif SOURCE_ENGINE == SE_CONTAGION + CONMSG(" Engine: Contagion (2013)\n"); +#elif SOURCE_ENGINE == SE_LEFT4DEAD + CONMSG(" Engine: Left 4 Dead (2008)\n"); +#elif SOURCE_ENGINE == SE_ORANGEBOX + CONMSG(" Engine: Episode 2 (Orange Box, 2007)\n"); +#elif SOURCE_ENGINE == SE_CSS + CONMSG(" Engine: Counter-Strike: Source (Valve Orange Box)\n"); +#elif SOURCE_ENGINE == SE_HL2DM + CONMSG(" Engine: Half-Life 2 Deathmatch (Valve Orange Box)\n"); +#elif SOURCE_ENGINE == SE_DODS + CONMSG(" Engine: Day of Defeat: Source (Valve Orange Box)\n"); +#elif SOURCE_ENGINE == SE_SDK2013 + CONMSG(" Engine: Source SDK 2013 (2013)\n"); +#elif SOURCE_ENGINE == SE_BMS + CONMSG(" Engine: Black Mesa (2015)\n"); +#elif SOURCE_ENGINE == SE_TF2 + CONMSG(" Engine: Team Fortress 2 (Valve Orange Box)\n"); +#elif SOURCE_ENGINE == SE_DARKMESSIAH + CONMSG(" Engine: Dark Messiah (2006)\n"); +#elif SOURCE_ENGINE == SE_EYE + CONMSG(" Engine: E.Y.E. Divine Cybermancy (2011)\n"); +#elif SOURCE_ENGINE == SE_PORTAL2 + CONMSG(" Engine: Portal 2 (2011)\n"); +#elif SOURCE_ENGINE == SE_BLADE + CONMSG(" Engine: Blade Symphony (2013)\n"); +#elif SOURCE_ENGINE == SE_INSURGENCY + CONMSG(" Engine: Insurgency (2013)\n"); +#elif SOURCE_ENGINE == SE_DOI + CONMSG(" Engine: Day of Infamy (2016)\n"); +#elif SOURCE_ENGINE == SE_CSGO + CONMSG(" Engine: Counter-Strike: Global Offensive (2012)\n"); +#elif SOURCE_ENGINE == SE_DOTA + CONMSG(" Engine: Dota 2 (2013)\n"); +#else +#error "SOURCE_ENGINE not defined to a known value" +#endif // Display user messages const char *msgname; @@ -671,13 +698,22 @@ bool Command_ClientMeta(edict_t *client, IMetamodSourceCommandInfo *info) if (strcmp(subcmd, "credits") == 0) { - ReplyCredits(client); + CLIENT_CONMSG(client, "Metamod:Source was developed by:\n"); + CLIENT_CONMSG(client, " SourceHook: Pavol \"PM OnoTo\" Marko\n"); + CLIENT_CONMSG(client, " GameDLL/Plugins: David \"BAILOPAN\" Anderson\n"); + CLIENT_CONMSG(client, " GameDLL: Scott \"DS\" Ehlert\n"); + CLIENT_CONMSG(client, "For more information, see the official website\n"); + CLIENT_CONMSG(client, "http://www.metamodsource.net/\n"); return true; } else if(strcmp(subcmd, "version") == 0) { - ReplyVersion(client); + CLIENT_CONMSG(client, "Metamod:Source version %s\n", METAMOD_VERSION); + CLIENT_CONMSG(client, "Compiled on: %s\n", SOURCEMM_DATE); + CLIENT_CONMSG(client, "Plugin interface version: %d:%d\n", METAMOD_PLAPI_VERSION, PLAPI_MIN_VERSION); + CLIENT_CONMSG(client, "SourceHook version: %d:%d\n", g_SHPtr->GetIfaceVersion(), g_SHPtr->GetImplVersion()); + CLIENT_CONMSG(client, "http://www.metamodsource.net/\n"); return true; } diff --git a/utils/mmsource/core/metamod_oslink.cpp b/utils/mmsource/core/metamod_oslink.cpp index a100ea72..2ec065d4 100644 --- a/utils/mmsource/core/metamod_oslink.cpp +++ b/utils/mmsource/core/metamod_oslink.cpp @@ -94,7 +94,7 @@ bool GetFileOfAddress(void *pAddr, char *buffer, size_t maxlength) return true; } -#if defined __GNUC__ +#if defined __GNUC__ && (__GNUC__ == 3 || __GNUC__ == 4) void * operator new(size_t size) { return malloc(size); } diff --git a/utils/mmsource/core/metamod_oslink.h b/utils/mmsource/core/metamod_oslink.h index a2b579c2..03b67646 100644 --- a/utils/mmsource/core/metamod_oslink.h +++ b/utils/mmsource/core/metamod_oslink.h @@ -90,7 +90,11 @@ bool GetFileOfAddress(void *pAddr, char *buffer, size_t maxlength); #if defined __WIN32__ || defined _WIN32 || defined WIN32 #define SMM_API extern "C" __declspec(dllexport) #elif defined __GNUC__ - #define SMM_API extern "C" __attribute__ ((visibility("default"))) + #if (__GNUC__ == 4) + #define SMM_API extern "C" __attribute__ ((visibility("default"))) + #else + #define SMM_API extern "C" + #endif #endif #if defined __WIN32__ || defined _WIN32 || defined WIN32 @@ -100,6 +104,10 @@ bool GetFileOfAddress(void *pAddr, char *buffer, size_t maxlength); typedef unsigned __int32 uint32_t; #elif defined __GNUC__ #include +#if !__GLIBC_HAVE_LONG_LONG + typedef long long int64_t; + typedef unsigned long long uint64_t; +#endif #endif #if !defined __linux__ && !defined __APPLE__ diff --git a/utils/mmsource/core/metamod_provider.h b/utils/mmsource/core/metamod_provider.h index eda81773..843151eb 100644 --- a/utils/mmsource/core/metamod_provider.h +++ b/utils/mmsource/core/metamod_provider.h @@ -37,16 +37,9 @@ namespace SourceMM enum ProvidedHooks { -#if SOURCE_ENGINE == SE_DOTA - ProvidedHook_StartChangeLevel = 0, - ProvidedHook_Init = 1, - ProvidedHook_StartupServer = 2, - ProvidedHook_SwitchToLoop = 3, -#else ProvidedHook_LevelInit = 0, /**< IServerGameDLL::LevelInit */ ProvidedHook_LevelShutdown = 1, /**< IServerGameDLL::LevelShutdown */ ProvidedHook_GameInit = 4, /**< IServerGameDLL::GameInit */ -#endif }; /** @@ -303,13 +296,6 @@ namespace SourceMM * */ virtual bool ProcessVDF(const char *file, char path[], size_t path_len, char alias[], size_t alias_len) =0; - - /** - * @brief Returns string that describes engine version. - * - * @return Description. - */ - virtual const char *GetEngineDescription() const =0; }; }; diff --git a/utils/mmsource/core/provider/console.cpp b/utils/mmsource/core/provider/console.cpp index a1362c68..abcf680e 100644 --- a/utils/mmsource/core/provider/console.cpp +++ b/utils/mmsource/core/provider/console.cpp @@ -69,7 +69,7 @@ void SMConVarAccessor::RemoveMetamodCommands() } } -#if SOURCE_ENGINE < SE_ORANGEBOX +#if SOURCE_ENGINE == SE_DARKMESSIAH /* Signature for ICvar::GetCommands() in vstdlib for Win32 and Linux. * * 20226EE0 A1 50 5C 5A 20 mov eax,dword ptr ds:[205A5C50h] <-- What we want diff --git a/utils/mmsource/core/provider/console.h b/utils/mmsource/core/provider/console.h index 20139b6c..08625f31 100644 --- a/utils/mmsource/core/provider/console.h +++ b/utils/mmsource/core/provider/console.h @@ -40,7 +40,7 @@ class SMConVarAccessor : public IConCommandBaseAccessor bool Register(ConCommandBase *pCommand); void Unregister(ConCommandBase *pCommand); void RemoveMetamodCommands(); -#if SOURCE_ENGINE < SE_ORANGEBOX +#if SOURCE_ENGINE == SE_DARKMESSIAH bool InitConCommandBaseList(); private: ConCommandBase **m_TopConCommandBase; diff --git a/utils/mmsource/core/provider/provider_ep2.cpp b/utils/mmsource/core/provider/provider_ep2.cpp index 445f5030..509303f2 100644 --- a/utils/mmsource/core/provider/provider_ep2.cpp +++ b/utils/mmsource/core/provider/provider_ep2.cpp @@ -38,18 +38,6 @@ #include "metamod_console.h" #include #include "metamod.h" -#include -#if SOURCE_ENGINE == SE_DOTA -#include -#endif - -#if SOURCE_ENGINE == SE_DOTA && defined( _WIN32 ) -SH_DECL_HOOK1(ISource2ServerConfig, AllowDedicatedServers, const, 0, bool, EUniverse); -bool BaseProvider::AllowDedicatedServers(EUniverse universe) const -{ - RETURN_META_VALUE(MRES_SUPERCEDE, true); -} -#endif /* Types */ typedef void (*CONPRINTF_FUNC)(const char *, ...); @@ -66,27 +54,22 @@ struct UsrMsgInfo }; /* Imports */ -#if SOURCE_ENGINE < SE_ORANGEBOX +#if SOURCE_ENGINE == SE_DARKMESSIAH #undef CommandLine DLL_IMPORT ICommandLine *CommandLine(); #endif /* Functions */ void CacheUserMessages(); -bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL); void Detour_Error(const tchar *pMsg, ...); - #if SOURCE_ENGINE == SE_DOTA void ClientCommand(CEntityIndex index, const CCommand &args); +void LocalCommand_Meta(const CCommandContext &context, const CCommand &args); #elif SOURCE_ENGINE >= SE_ORANGEBOX void ClientCommand(edict_t *pEdict, const CCommand &args); -#else -void ClientCommand(edict_t *pEdict); -#endif - -#if SOURCE_ENGINE >= SE_ORANGEBOX void LocalCommand_Meta(const CCommand &args); #else +void ClientCommand(edict_t *pEdict); void LocalCommand_Meta(); #endif @@ -96,19 +79,12 @@ static BaseProvider g_Ep1Provider; static List conbases_unreg; static CVector usermsgs_list; static jmp_buf usermsg_end; -static bool g_bOriginalEngine = false; ICvar *icvar = NULL; IFileSystem *baseFs = NULL; IServerGameDLL *server = NULL; -#if SOURCE_ENGINE == SE_DOTA -static ISource2ServerConfig *serverconfig = NULL; -INetworkServerService *netservice = NULL; -IEngineServiceMgr *enginesvcmgr = NULL; -#endif IVEngineServer *engine = NULL; IServerGameClients *gameclients = NULL; -CGlobalVars *gpGlobals = NULL; IMetamodSourceProvider *provider = &g_Ep1Provider; ConCommand meta_local_cmd("meta", LocalCommand_Meta, "Metamod:Source control options"); @@ -151,12 +127,6 @@ void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory, DisplayError("Could not find IVEngineServer! Metamod cannot load."); return; } -#if SOURCE_ENGINE == SE_DOTA - gpGlobals = engine->GetServerGlobals(); - serverconfig = (ISource2ServerConfig *) ((serverFactory) (INTERFACEVERSION_SERVERCONFIG, NULL)); - netservice = (INetworkServerService *) ((engineFactory) (NETWORKSERVERSERVICE_INTERFACE_VERSION, NULL)); - enginesvcmgr = (IEngineServiceMgr *) ((engineFactory) (ENGINESERVICEMGR_INTERFACE_VERSION, NULL)); -#endif #if SOURCE_ENGINE >= SE_ORANGEBOX icvar = (ICvar *)((engineFactory)(CVAR_INTERFACE_VERSION, NULL)); #else @@ -168,15 +138,12 @@ void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory, return; } -#if SOURCE_ENGINE == SE_DOTA - gameclients = (IServerGameClients *)(serverFactory(INTERFACEVERSION_SERVERGAMECLIENTS, NULL)); -#else + if ((gameclients = (IServerGameClients *)(serverFactory("ServerGameClients003", NULL))) == NULL) { gameclients = (IServerGameClients *)(serverFactory("ServerGameClients004", NULL)); } -#endif baseFs = (IFileSystem *)((engineFactory)(FILESYSTEM_INTERFACE_VERSION, NULL)); if (baseFs == NULL) @@ -184,55 +151,15 @@ void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory, mm_LogMessage("Unable to find \"%s\": .vdf files will not be parsed", FILESYSTEM_INTERFACE_VERSION); } -#if SOURCE_ENGINE == SE_DOTA - // Since we have to be added as a Game path (cannot add GameBin directly), we - // automatically get added to other paths as well, including having the MM:S - // dir become the default write path for logs and more. We can fix some of these. - - char searchPath[260]; - baseFs->GetSearchPath("GAME", (GetSearchPathTypes_t)0, searchPath, sizeof(searchPath)); - for (size_t i = 0; i < sizeof(searchPath); ++i) - { - if (searchPath[i] == ';') - { - searchPath[i] = '\0'; - break; - } - } - baseFs->RemoveSearchPath(searchPath, "GAME"); - - // TODO: figure out why these calls get ignored and path remains - //baseFs->RemoveSearchPath(searchPath, "CONTENT"); - //baseFs->RemoveSearchPath(searchPath, "SHADER_SOURCE"); - //baseFs->RemoveSearchPath(searchPath, "SHADER_SOURCE_MOD"); - - baseFs->RemoveSearchPaths("DEFAULT_WRITE_PATH"); - baseFs->GetSearchPath("GAME", (GetSearchPathTypes_t)0, searchPath, sizeof(searchPath)); - for (size_t i = 0; i < sizeof(searchPath); ++i) - { - if (searchPath[i] == ';') - { - searchPath[i] = '\0'; - break; - } - } - baseFs->AddSearchPath(searchPath, "DEFAULT_WRITE_PATH"); -#endif - #if SOURCE_ENGINE >= SE_ORANGEBOX g_pCVar = icvar; #endif g_SMConVarAccessor.RegisterConCommandBase(&meta_local_cmd); - -#if SOURCE_ENGINE == SE_EPISODEONE - /* The Ship is the only game known at this time that uses the pre-Episode One engine */ - g_bOriginalEngine = strcmp(CommandLine()->ParmValue("-game", "hl2"), "ship") == 0; -#endif CacheUserMessages(); -#if SOURCE_ENGINE < SE_ORANGEBOX +#if SOURCE_ENGINE == SE_DARKMESSIAH if (!g_SMConVarAccessor.InitConCommandBaseList()) { /* This is very unlikely considering it's old engine */ @@ -245,17 +172,13 @@ void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory, { SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, gameclients, ClientCommand, false); } - -#if SOURCE_ENGINE == SE_DOTA && defined( _WIN32 ) - SH_ADD_VPHOOK(ISource2ServerConfig, AllowDedicatedServers, serverconfig, SH_MEMBER(this, &BaseProvider::AllowDedicatedServers), false); -#endif } void BaseProvider::Notify_DLLShutdown_Pre() { g_SMConVarAccessor.RemoveMetamodCommands(); -#if SOURCE_ENGINE < SE_ORANGEBOX +#if SOURCE_ENGINE == SE_DARKMESSIAH if (g_Metamod.IsLoadedAsGameDLL()) { icvar->UnlinkVariables(FCVAR_GAMEDLL); @@ -271,7 +194,7 @@ bool BaseProvider::IsRemotePrintingAvailable() void BaseProvider::ClientConsolePrint(edict_t *pEdict, const char *message) { #if SOURCE_ENGINE == SE_DOTA - int client = (int)(pEdict - gpGlobals->pEdicts); + int client = (int)(pEdict - g_Metamod.GetCGlobals()->pEdicts); engine->ClientPrintf(client, message); #else engine->ClientPrintf(pEdict, message); @@ -354,31 +277,6 @@ bool BaseProvider::LogMessage(const char *buffer) bool BaseProvider::GetHookInfo(ProvidedHooks hook, SourceHook::MemFuncInfo *pInfo) { -#if SOURCE_ENGINE == SE_DOTA - SourceHook::MemFuncInfo mfi = {true, -1, 0, 0}; - - switch (hook) - { - case ProvidedHook_StartupServer: - SourceHook::GetFuncInfo(&INetworkServerService::StartupServer, mfi); - break; - case ProvidedHook_StartChangeLevel: - SourceHook::GetFuncInfo(&INetworkGameServer::StartChangeLevel, mfi); - break; - case ProvidedHook_Init: - SourceHook::GetFuncInfo(&INetworkGameServer::Init, mfi); - break; - case ProvidedHook_SwitchToLoop: - SourceHook::GetFuncInfo(&IEngineServiceMgr::SwitchToLoop, mfi); - break; - default: - return false; - } - - *pInfo = mfi; - - return (mfi.thisptroffs >= 0); -#else SourceHook::MemFuncInfo mfi = {true, -1, 0, 0}; if (hook == ProvidedHook_LevelInit) @@ -397,7 +295,6 @@ bool BaseProvider::GetHookInfo(ProvidedHooks hook, SourceHook::MemFuncInfo *pInf *pInfo = mfi; return (mfi.thisptroffs >= 0); -#endif } void BaseProvider::DisplayError(const char *fmt, ...) @@ -487,11 +384,7 @@ void BaseProvider::GetGamePath(char *pszBuffer, int len) const char *BaseProvider::GetGameDescription() { -#if SOURCE_ENGINE == SE_DOTA - return serverconfig->GetGameDescription(); -#else return server->GetGameDescription(); -#endif } int BaseProvider::DetermineSourceEngine() @@ -538,8 +431,6 @@ int BaseProvider::DetermineSourceEngine() return SOURCE_ENGINE_DOTA; #elif SOURCE_ENGINE == SE_BMS return SOURCE_ENGINE_BMS; -#elif SOURCE_ENGINE == SE_EPISODEONE - return g_bOriginalEngine ? SOURCE_ENGINE_ORIGINAL : SOURCE_ENGINE_EPISODEONE; #else #error "SOURCE_ENGINE not defined to a known value" #endif @@ -575,22 +466,11 @@ bool BaseProvider::ProcessVDF(const char *file, char path[], size_t path_len, ch } KeyValues *pValues; - bool bKVLoaded = false; const char *plugin_file, *p_alias; pValues = new KeyValues("Metamod Plugin"); - if (g_bOriginalEngine) - { - /* The Ship must use a special version of this function */ - bKVLoaded = KVLoadFromFile(pValues, baseFs, file); - } - else - { - bKVLoaded = pValues->LoadFromFile(baseFs, file); - } - - if (!bKVLoaded) + if (!pValues->LoadFromFile(baseFs, file)) { pValues->deleteThis(); return false; @@ -618,64 +498,6 @@ bool BaseProvider::ProcessVDF(const char *file, char path[], size_t path_len, ch return true; } -const char *BaseProvider::GetEngineDescription() const -{ -#if SOURCE_ENGINE == SE_BLOODYGOODTIME - return "Bloody Good Time (2010)"; -#elif SOURCE_ENGINE == SE_ALIENSWARM - return "Alien Swarm (2010)"; -#elif SOURCE_ENGINE == SE_LEFT4DEAD2 - return "Left 4 Dead 2 (2009)"; -#elif SOURCE_ENGINE == SE_NUCLEARDAWN - return "Nuclear Dawn (2011)"; -#elif SOURCE_ENGINE == SE_CONTAGION - return "Contagion (2013)"; -#elif SOURCE_ENGINE == SE_LEFT4DEAD - return "Left 4 Dead (2008)"; -#elif SOURCE_ENGINE == SE_ORANGEBOX - return "Episode 2 (Orange Box, 2007)"; -#elif SOURCE_ENGINE == SE_CSS - return "Counter-Strike: Source (Valve Orange Box)"; -#elif SOURCE_ENGINE == SE_HL2DM - return "Half-Life 2 Deathmatch (Valve Orange Box)"; -#elif SOURCE_ENGINE == SE_DODS - return "Day of Defeat: Source (Valve Orange Box)"; -#elif SOURCE_ENGINE == SE_SDK2013 - return "Source SDK 2013 (2013)"; -#elif SOURCE_ENGINE == SE_BMS - return "Black Mesa (2015)"; -#elif SOURCE_ENGINE == SE_TF2 - return "Team Fortress 2 (Valve Orange Box)"; -#elif SOURCE_ENGINE == SE_DARKMESSIAH - return "Dark Messiah (2006)"; -#elif SOURCE_ENGINE == SE_EYE - return "E.Y.E. Divine Cybermancy (2011)"; -#elif SOURCE_ENGINE == SE_PORTAL2 - return "Portal 2 (2011)"; -#elif SOURCE_ENGINE == SE_BLADE - return "Blade Symphony (2013)"; -#elif SOURCE_ENGINE == SE_INSURGENCY - return "Insurgency (2013)"; -#elif SOURCE_ENGINE == SE_DOI - return "Day of Infamy (2016)"; -#elif SOURCE_ENGINE == SE_CSGO - return "Counter-Strike: Global Offensive (2012)"; -#elif SOURCE_ENGINE == SE_DOTA - return "Dota 2 (2013)"; -#elif SOURCE_ENGINE == SE_EPISODEONE - if (g_bOriginalEngine) - { - return "Original (pre-Episode 1)"; - } - else - { - return "Episode 1 (2004)"; - } -#else -#error "SOURCE_ENGINE not defined to a known value" -#endif -} - #if SOURCE_ENGINE >= SE_ORANGEBOX class GlobCommand : public IMetamodSourceCommandInfo { @@ -722,7 +544,11 @@ class GlobCommand : public IMetamodSourceCommandInfo }; #endif -#if SOURCE_ENGINE >= SE_ORANGEBOX +#if SOURCE_ENGINE == SE_DOTA +void LocalCommand_Meta(const CCommandContext &context, const CCommand &args) +{ + GlobCommand cmd(&args); +#elif SOURCE_ENGINE >= SE_ORANGEBOX void LocalCommand_Meta(const CCommand &args) { GlobCommand cmd(&args); @@ -823,33 +649,3 @@ void CacheUserMessages() } #endif - -bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID) -{ - Assert(filesystem); -#ifdef _MSC_VER - Assert(_heapchk() == _HEAPOK); -#endif - - FileHandle_t f = filesystem->Open(resourceName, "rb", pathID); - if (!f) - return false; - - // load file into a null-terminated buffer - int fileSize = filesystem->Size(f); - char *buffer = (char *)MemAllocScratch(fileSize + 1); - - Assert(buffer); - - filesystem->Read(buffer, fileSize, f); // read into local buffer - - buffer[fileSize] = 0; // null terminate file as EOF - - filesystem->Close( f ); // close file after reading - - bool retOK = kv->LoadFromBuffer( resourceName, buffer, filesystem ); - - MemFreeScratch(); - - return retOK; -} diff --git a/utils/mmsource/core/provider/provider_ep2.h b/utils/mmsource/core/provider/provider_ep2.h index 99c75868..f710438c 100644 --- a/utils/mmsource/core/provider/provider_ep2.h +++ b/utils/mmsource/core/provider/provider_ep2.h @@ -32,9 +32,7 @@ #endif #include #include -#if SOURCE_ENGINE != SE_DOTA #include -#endif #include "ISmmAPI.h" #include "metamod_provider.h" #include "metamod_oslink.h" @@ -46,8 +44,6 @@ using namespace SourceMM; using namespace SourceHook; -class INetworkGameServer; - class BaseProvider : public IMetamodSourceProvider { public: @@ -81,21 +77,12 @@ class BaseProvider : public IMetamodSourceProvider virtual const char *GetUserMessage(int index, int *size=NULL); virtual int DetermineSourceEngine(); virtual bool ProcessVDF(const char *file, char path[], size_t path_len, char alias[], size_t alias_len); - virtual const char *GetEngineDescription() const; -#if SOURCE_ENGINE == SE_DOTA && defined( _WIN32 ) - bool AllowDedicatedServers(EUniverse universe) const; -#endif }; extern IVEngineServer *engine; extern IServerGameDLL *server; extern IServerGameClients *gameclients; extern ICvar *icvar; -extern CGlobalVars *gpGlobals; -#if SOURCE_ENGINE == SE_DOTA -extern INetworkServerService *netservice; -extern IEngineServiceMgr *enginesvcmgr; -#endif #endif //_INCLUDE_METAMOD_SOURCE_BASE_PROVIDER_H_ diff --git a/utils/mmsource/core/sourcehook/FastDelegate.h b/utils/mmsource/core/sourcehook/FastDelegate.h index 53a3964c..665c5583 100644 --- a/utils/mmsource/core/sourcehook/FastDelegate.h +++ b/utils/mmsource/core/sourcehook/FastDelegate.h @@ -44,11 +44,6 @@ // * Fully supported by CodePlay VectorC // * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC! // * More optimal assignment,== and != operators for static function pointers. -// -// AlliedModders LLC modifications. -// -// 24-Oct-15 1.6 * Use C++11 variadic templates. -// #ifndef FASTDELEGATE_H #define FASTDELEGATE_H @@ -857,214 +852,2956 @@ class ClosurePtr : public DelegateMemento { // in that case the static function constructor is not made explicit; this // allows "if (dg==0) ..." to compile. -template -class FastDelegate { +//N=0 +template +class FastDelegate0 { private: typedef typename detail::DefaultVoidToVoid::type DesiredRetType; - typedef DesiredRetType (*StaticFunctionPtr)(Params... params); - typedef RetType (*UnvoidStaticFunctionPtr)(Params... params); - typedef RetType (detail::GenericClass::*GenericMemFn)(Params... params); + typedef DesiredRetType (*StaticFunctionPtr)(); + typedef RetType (*UnvoidStaticFunctionPtr)(); + typedef RetType (detail::GenericClass::*GenericMemFn)(); typedef detail::ClosurePtr ClosureType; ClosureType m_Closure; public: // Typedefs to aid generic programming - typedef FastDelegate type; + typedef FastDelegate0 type; // Construction and comparison functions - FastDelegate() { - clear(); - } - FastDelegate(const FastDelegate &x) { - m_Closure.CopyFrom(this, x.m_Closure); - } - void operator = (const FastDelegate &x) { - m_Closure.CopyFrom(this, x.m_Closure); - } - bool operator ==(const FastDelegate &x) const { - return m_Closure.IsEqual(x.m_Closure); - } - bool operator !=(const FastDelegate &x) const { - return !m_Closure.IsEqual(x.m_Closure); - } - bool operator <(const FastDelegate &x) const { - return m_Closure.IsLess(x.m_Closure); - } - bool operator >(const FastDelegate &x) const { - return x.m_Closure.IsLess(m_Closure); - } + FastDelegate0() { clear(); } + FastDelegate0(const FastDelegate0 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate0 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate0 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate0 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate0 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate0 &x) const { + return x.m_Closure.IsLess(m_Closure); } // Binding to non-const member functions template < class X, class Y > - FastDelegate(Y *pthis, DesiredRetType (X::* function_to_bind)(Params... params) ) { - m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); - } + FastDelegate0(Y *pthis, DesiredRetType (X::* function_to_bind)() ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } template < class X, class Y > - inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Params... params)) { - m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); - } + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)()) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Binding to const member functions. template < class X, class Y > - FastDelegate(const Y *pthis, DesiredRetType (X::* function_to_bind)(Params... params) const) { - m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); - } + FastDelegate0(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } template < class X, class Y > - inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Params... params) const) { - m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); - } + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } // Static functions. We convert them into a member function call. // This constructor also provides implicit conversion - FastDelegate(DesiredRetType (*function_to_bind)(Params... params) ) { - bind(function_to_bind); - } + FastDelegate0(DesiredRetType (*function_to_bind)() ) { + bind(function_to_bind); } // for efficiency, prevent creation of a temporary - void operator = (DesiredRetType (*function_to_bind)(Params... params) ) { - bind(function_to_bind); - } - inline void bind(DesiredRetType (*function_to_bind)(Params... params)) { - m_Closure.bindstaticfunc(this, &FastDelegate::InvokeStaticFunction, function_to_bind); - } + void operator = (DesiredRetType (*function_to_bind)() ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)()) { + m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction, + function_to_bind); } // Invoke the delegate - RetType operator() (Params... params) const { - return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(params...); - } + RetType operator() () const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); } // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { int a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; - typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; public: operator unspecified_bool_type() const { - return empty() ? 0: &SafeBoolStruct::m_nonzero; - } + return empty()? 0: &SafeBoolStruct::m_nonzero; + } // necessary to allow ==0 to work despite the safe_bool idiom inline bool operator==(StaticFunctionPtr funcptr) { - return m_Closure.IsEqualToStaticFuncPtr(funcptr); - } + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator!=(StaticFunctionPtr funcptr) { - return !m_Closure.IsEqualToStaticFuncPtr(funcptr); - } + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } inline bool operator ! () const { // Is it bound to anything? - return !m_Closure; - } - inline bool empty() const { - return !m_Closure; - } - void clear() { - m_Closure.clear(); - } + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} // Conversion to and from the DelegateMemento storage class - const DelegateMemento & GetMemento() { - return m_Closure; - } - void SetMemento(const DelegateMemento &any) { - m_Closure.CopyFrom(this, any); - } + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } -private: - // Invoker for static functions - RetType InvokeStaticFunction(Params... params) const { - return (*(m_Closure.GetStaticFunction()))(params...); - } +private: // Invoker for static functions + RetType InvokeStaticFunction() const { + return (*(m_Closure.GetStaticFunction()))(); } }; -//////////////////////////////////////////////////////////////////////////////// -// Fast Delegates, part 4: -// -// FastDelegate<> class (Original author: Jody Hagins) -// Allows boost::function style syntax like: -// FastDelegate< double (int, long) > -// instead of: -// FastDelegate2< int, long, double > -// -//////////////////////////////////////////////////////////////////////////////// +//N=1 +template +class FastDelegate1 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate1 type; -#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + // Construction and comparison functions + FastDelegate1() { clear(); } + FastDelegate1(const FastDelegate1 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate1 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate1 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate1 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate1 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate1 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate1(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate1(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1)) { + m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } -//N=0 -// Specialization to allow use of -// FastDelegate< R ( ) > -// instead of -// FastDelegate0 < R > -template -class FastDelegate< R (Params...) > - // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0 - : public FastDelegate < R, Params... > -{ +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1) const { + return (*(m_Closure.GetStaticFunction()))(p1); } +}; + +//N=2 +template +class FastDelegate2 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; public: - // Make using the base type a bit easier via typedef. - typedef FastDelegate < R, Params... > BaseType; + // Typedefs to aid generic programming + typedef FastDelegate2 type; - // Allow users access to the specific type of this delegate. - typedef FastDelegate SelfType; + // Construction and comparison functions + FastDelegate2() { clear(); } + FastDelegate2(const FastDelegate2 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate2 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate2 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate2 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate2 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate2 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate2(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate2(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2)) { + m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } - // Mimic the base class constructors. - FastDelegate() : BaseType() { } +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2); } +}; - template < class X, class Y > - FastDelegate(Y * pthis, - R (X::* function_to_bind)(Params... params)) - : BaseType(pthis, function_to_bind) { } +//N=3 +template +class FastDelegate3 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate3 type; - template < class X, class Y > - FastDelegate(const Y *pthis, - R (X::* function_to_bind)(Params... params) const) - : BaseType(pthis, function_to_bind) - { } + // Construction and comparison functions + FastDelegate3() { clear(); } + FastDelegate3(const FastDelegate3 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate3 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate3 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate3 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate3 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate3 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate3(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate3(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } - FastDelegate(R (*function_to_bind)(Params... params)) - : BaseType(function_to_bind) { } - void operator = (const BaseType &x) { - *static_cast(this) = x; } +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3); } }; -#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +//N=4 +template +class FastDelegate4 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate4 type; -//////////////////////////////////////////////////////////////////////////////// -// Fast Delegates, part 5: -// -// MakeDelegate() helper function -// -// MakeDelegate(&x, &X::func) returns a fastdelegate of the type -// necessary for calling x.func() with the correct number of arguments. -// This makes it possible to eliminate many typedefs from user code. -// -//////////////////////////////////////////////////////////////////////////////// + // Construction and comparison functions + FastDelegate4() { clear(); } + FastDelegate4(const FastDelegate4 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate4 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate4 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate4 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate4 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate4 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate4(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate4(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } -// Also declare overloads of a MakeDelegate() global function to -// reduce the need for typedefs. -// We need seperate overloads for const and non-const member functions. -// Also, because of the weird rule about the class of derived member function pointers, -// implicit downcasts may need to be applied later to the 'this' pointer. -// That's why two classes (X and Y) appear in the definitions. Y must be implicitly -// castable to X. +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4); } +}; -// Workaround for VC6. VC6 needs void return types converted into DefaultVoid. -// GCC 3.2 and later won't compile this unless it's preceded by 'typename', -// but VC6 doesn't allow 'typename' in this context. -// So, I have to use a macro. +//N=5 +template +class FastDelegate5 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate5 type; -#ifdef FASTDLGT_VC6 -#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid::type -#else -#define FASTDLGT_RETTYPE RetType -#endif + // Construction and comparison functions + FastDelegate5() { clear(); } + FastDelegate5(const FastDelegate5 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate5 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate5 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate5 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate5 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate5 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate5(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate5(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } -//N=1 -template -FastDelegate MakeDelegate(Y* x, RetType (X::*func)(Params... params)) { - return FastDelegate(x, func); -} +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5); } +}; -template -FastDelegate MakeDelegate(Y* x, RetType (X::*func)(Params... params) const) { - return FastDelegate(x, func); -} +//N=6 +template +class FastDelegate6 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate6 type; + + // Construction and comparison functions + FastDelegate6() { clear(); } + FastDelegate6(const FastDelegate6 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate6 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate6 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate6 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate6 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate6 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate6(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate6(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6); } +}; + +//N=7 +template +class FastDelegate7 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate7 type; + + // Construction and comparison functions + FastDelegate7() { clear(); } + FastDelegate7(const FastDelegate7 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate7 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate7 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate7 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate7 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate7 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate7(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate7(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7); } +}; + +//N=8 +template +class FastDelegate8 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate8 type; + + // Construction and comparison functions + FastDelegate8() { clear(); } + FastDelegate8(const FastDelegate8 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate8 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate8 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate8 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate8 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate8 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate8(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate8(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8); } +}; + +//N=9 +template +class FastDelegate9 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate9 type; + + // Construction and comparison functions + FastDelegate9() { clear(); } + FastDelegate9(const FastDelegate9 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate9 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate9 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate9 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate9 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate9 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate9(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate9(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate9(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { + m_Closure.bindstaticfunc(this, &FastDelegate9::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9); } +}; + +//N=10 +template +class FastDelegate10 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate10 type; + + // Construction and comparison functions + FastDelegate10() { clear(); } + FastDelegate10(const FastDelegate10 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate10 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate10 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate10 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate10 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate10 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate10(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate10(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate10(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { + m_Closure.bindstaticfunc(this, &FastDelegate10::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } +}; + +//N=11 +template +class FastDelegate11 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate11 type; + + // Construction and comparison functions + FastDelegate11() { clear(); } + FastDelegate11(const FastDelegate11 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate11 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate11 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate11 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate11 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate11 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate11(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate11(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate11(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + m_Closure.bindstaticfunc(this, &FastDelegate11::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } +}; + +//N=12 +template +class FastDelegate12 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate12 type; + + // Construction and comparison functions + FastDelegate12() { clear(); } + FastDelegate12(const FastDelegate12 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate12 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate12 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate12 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate12 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate12 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate12(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate12(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate12(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + m_Closure.bindstaticfunc(this, &FastDelegate12::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } +}; + +//N=13 +template +class FastDelegate13 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate13 type; + + // Construction and comparison functions + FastDelegate13() { clear(); } + FastDelegate13(const FastDelegate13 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate13 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate13 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate13 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate13 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate13 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate13(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate13(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate13(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + m_Closure.bindstaticfunc(this, &FastDelegate13::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } +}; + +//N=14 +template +class FastDelegate14 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate14 type; + + // Construction and comparison functions + FastDelegate14() { clear(); } + FastDelegate14(const FastDelegate14 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate14 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate14 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate14 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate14 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate14 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate14(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate14(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate14(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { + m_Closure.bindstaticfunc(this, &FastDelegate14::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); } +}; + +//N=15 +template +class FastDelegate15 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate15 type; + + // Construction and comparison functions + FastDelegate15() { clear(); } + FastDelegate15(const FastDelegate15 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate15 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate15 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate15 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate15 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate15 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate15(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate15(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate15(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { + m_Closure.bindstaticfunc(this, &FastDelegate15::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); } +}; + +//N=16 +template +class FastDelegate16 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate16 type; + + // Construction and comparison functions + FastDelegate16() { clear(); } + FastDelegate16(const FastDelegate16 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate16 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate16 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate16 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate16 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate16 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate16(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate16(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate16(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { + m_Closure.bindstaticfunc(this, &FastDelegate16::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16); } +}; + +//N=17 +template +class FastDelegate17 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate17 type; + + // Construction and comparison functions + FastDelegate17() { clear(); } + FastDelegate17(const FastDelegate17 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate17 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate17 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate17 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate17 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate17 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate17(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate17(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate17(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { + m_Closure.bindstaticfunc(this, &FastDelegate17::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17); } +}; + +//N=18 +template +class FastDelegate18 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate18 type; + + // Construction and comparison functions + FastDelegate18() { clear(); } + FastDelegate18(const FastDelegate18 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate18 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate18 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate18 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate18 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate18 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate18(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate18(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate18(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { + m_Closure.bindstaticfunc(this, &FastDelegate18::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18); } +}; + +//N=19 +template +class FastDelegate19 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate19 type; + + // Construction and comparison functions + FastDelegate19() { clear(); } + FastDelegate19(const FastDelegate19 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate19 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate19 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate19 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate19 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate19 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate19(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate19(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate19(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { + m_Closure.bindstaticfunc(this, &FastDelegate19::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19); } +}; + +//N=20 +template +class FastDelegate20 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate20 type; + + // Construction and comparison functions + FastDelegate20() { clear(); } + FastDelegate20(const FastDelegate20 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate20 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate20 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate20 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate20 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate20 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate20(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate20(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate20(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { + m_Closure.bindstaticfunc(this, &FastDelegate20::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20); } +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 4: +// +// FastDelegate<> class (Original author: Jody Hagins) +// Allows boost::function style syntax like: +// FastDelegate< double (int, long) > +// instead of: +// FastDelegate2< int, long, double > +// +//////////////////////////////////////////////////////////////////////////////// + +#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +// Declare FastDelegate as a class template. It will be specialized +// later for all number of arguments. +template +class FastDelegate; + +//N=0 +// Specialization to allow use of +// FastDelegate< R ( ) > +// instead of +// FastDelegate0 < R > +template +class FastDelegate< R ( ) > + // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0 + : public FastDelegate0 < R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate0 < R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=1 +// Specialization to allow use of +// FastDelegate< R ( Param1 ) > +// instead of +// FastDelegate1 < Param1, R > +template +class FastDelegate< R ( Param1 ) > + // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1 + : public FastDelegate1 < Param1, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate1 < Param1, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=2 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2 ) > +// instead of +// FastDelegate2 < Param1, Param2, R > +template +class FastDelegate< R ( Param1, Param2 ) > + // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2 + : public FastDelegate2 < Param1, Param2, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate2 < Param1, Param2, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=3 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3 ) > +// instead of +// FastDelegate3 < Param1, Param2, Param3, R > +template +class FastDelegate< R ( Param1, Param2, Param3 ) > + // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3 + : public FastDelegate3 < Param1, Param2, Param3, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate3 < Param1, Param2, Param3, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=4 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4 ) > +// instead of +// FastDelegate4 < Param1, Param2, Param3, Param4, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4 ) > + // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4 + : public FastDelegate4 < Param1, Param2, Param3, Param4, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate4 < Param1, Param2, Param3, Param4, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=5 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > +// instead of +// FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > + // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5 + : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=6 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > +// instead of +// FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > + // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6 + : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=7 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > +// instead of +// FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > + // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7 + : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=8 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > +// instead of +// FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > + // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8 + : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=9 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9 ) > +// instead of +// FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9 ) > + // Inherit from FastDelegate9 so that it can be treated just like a FastDelegate9 + : public FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate9 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=10 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10 ) > +// instead of +// FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10 ) > + // Inherit from FastDelegate10 so that it can be treated just like a FastDelegate10 + : public FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate10 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=11 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11 ) > +// instead of +// FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11 ) > + // Inherit from FastDelegate11 so that it can be treated just like a FastDelegate11 + : public FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=12 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12 ) > +// instead of +// FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12 ) > + // Inherit from FastDelegate12 so that it can be treated just like a FastDelegate12 + : public FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=13 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13 ) > +// instead of +// FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13 ) > + // Inherit from FastDelegate13 so that it can be treated just like a FastDelegate13 + : public FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=14 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14 ) > +// instead of +// FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14 ) > + // Inherit from FastDelegate14 so that it can be treated just like a FastDelegate14 + : public FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate14 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=15 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15 ) > +// instead of +// FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15 ) > + // Inherit from FastDelegate15 so that it can be treated just like a FastDelegate15 + : public FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate15 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=16 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16 ) > +// instead of +// FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16 ) > + // Inherit from FastDelegate16 so that it can be treated just like a FastDelegate16 + : public FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate16 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=17 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17 ) > +// instead of +// FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17 ) > + // Inherit from FastDelegate17 so that it can be treated just like a FastDelegate17 + : public FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate17 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=18 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18 ) > +// instead of +// FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18 ) > + // Inherit from FastDelegate18 so that it can be treated just like a FastDelegate18 + : public FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate18 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=19 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19 ) > +// instead of +// FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19 ) > + // Inherit from FastDelegate19 so that it can be treated just like a FastDelegate19 + : public FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate19 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=20 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20 ) > +// instead of +// FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20 ) > + // Inherit from FastDelegate20 so that it can be treated just like a FastDelegate20 + : public FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate20 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + + +#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 5: +// +// MakeDelegate() helper function +// +// MakeDelegate(&x, &X::func) returns a fastdelegate of the type +// necessary for calling x.func() with the correct number of arguments. +// This makes it possible to eliminate many typedefs from user code. +// +//////////////////////////////////////////////////////////////////////////////// + +// Also declare overloads of a MakeDelegate() global function to +// reduce the need for typedefs. +// We need seperate overloads for const and non-const member functions. +// Also, because of the weird rule about the class of derived member function pointers, +// implicit downcasts may need to be applied later to the 'this' pointer. +// That's why two classes (X and Y) appear in the definitions. Y must be implicitly +// castable to X. + +// Workaround for VC6. VC6 needs void return types converted into DefaultVoid. +// GCC 3.2 and later won't compile this unless it's preceded by 'typename', +// but VC6 doesn't allow 'typename' in this context. +// So, I have to use a macro. + +#ifdef FASTDLGT_VC6 +#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid::type +#else +#define FASTDLGT_RETTYPE RetType +#endif + +//N=0 +template +FastDelegate0 MakeDelegate(Y* x, RetType (X::*func)()) { + return FastDelegate0(x, func); +} + +template +FastDelegate0 MakeDelegate(Y* x, RetType (X::*func)() const) { + return FastDelegate0(x, func); +} + +template +FastDelegate0 MakeDelegate(RetType (*func)()) { + return FastDelegate0(func); +} + +//N=1 +template +FastDelegate1 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1)) { + return FastDelegate1(x, func); +} + +template +FastDelegate1 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1) const) { + return FastDelegate1(x, func); +} + +template +FastDelegate1 MakeDelegate(RetType (*func)(Param1 p1)) { + return FastDelegate1(func); +} + +//N=2 +template +FastDelegate2 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2)) { + return FastDelegate2(x, func); +} + +template +FastDelegate2 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2) const) { + return FastDelegate2(x, func); +} + +template +FastDelegate2 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2)) { + return FastDelegate2(func); +} + +//N=3 +template +FastDelegate3 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3)) { + return FastDelegate3(x, func); +} + +template +FastDelegate3 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3) const) { + return FastDelegate3(x, func); +} + +template +FastDelegate3 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3)) { + return FastDelegate3(func); +} + +//N=4 +template +FastDelegate4 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + return FastDelegate4(x, func); +} + +template +FastDelegate4 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + return FastDelegate4(x, func); +} + +template +FastDelegate4 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + return FastDelegate4(func); +} + +//N=5 +template +FastDelegate5 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + return FastDelegate5(x, func); +} + +template +FastDelegate5 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + return FastDelegate5(x, func); +} + +template +FastDelegate5 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + return FastDelegate5(func); +} + +//N=6 +template +FastDelegate6 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + return FastDelegate6(x, func); +} + +template +FastDelegate6 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + return FastDelegate6(x, func); +} + +template +FastDelegate6 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + return FastDelegate6(func); +} + +//N=7 +template +FastDelegate7 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + return FastDelegate7(x, func); +} + +template +FastDelegate7 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + return FastDelegate7(x, func); +} + +template +FastDelegate7 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + return FastDelegate7(func); +} + +//N=8 +template +FastDelegate8 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + return FastDelegate8(x, func); +} + +template +FastDelegate8 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + return FastDelegate8(x, func); +} + +template +FastDelegate8 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + return FastDelegate8(func); +} + +//N=9 +template +FastDelegate9 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { + return FastDelegate9(x, func); +} + +template +FastDelegate9 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const) { + return FastDelegate9(x, func); +} + +template +FastDelegate9 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9)) { + return FastDelegate9(func); +} + +//N=10 +template +FastDelegate10 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { + return FastDelegate10(x, func); +} + +template +FastDelegate10 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const) { + return FastDelegate10(x, func); +} + +template +FastDelegate10 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10)) { + return FastDelegate10(func); +} + +//N=11 +template +FastDelegate11 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + return FastDelegate11(x, func); +} + +template +FastDelegate11 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { + return FastDelegate11(x, func); +} + +template +FastDelegate11 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + return FastDelegate11(func); +} + +//N=12 +template +FastDelegate12 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + return FastDelegate12(x, func); +} + +template +FastDelegate12 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { + return FastDelegate12(x, func); +} + +template +FastDelegate12 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + return FastDelegate12(func); +} + +//N=13 +template +FastDelegate13 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + return FastDelegate13(x, func); +} + +template +FastDelegate13 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { + return FastDelegate13(x, func); +} + +template +FastDelegate13 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + return FastDelegate13(func); +} + +//N=14 +template +FastDelegate14 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { + return FastDelegate14(x, func); +} + +template +FastDelegate14 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const) { + return FastDelegate14(x, func); +} + +template +FastDelegate14 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14)) { + return FastDelegate14(func); +} + +//N=15 +template +FastDelegate15 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { + return FastDelegate15(x, func); +} + +template +FastDelegate15 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const) { + return FastDelegate15(x, func); +} + +template +FastDelegate15 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15)) { + return FastDelegate15(func); +} + +//N=16 +template +FastDelegate16 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { + return FastDelegate16(x, func); +} + +template +FastDelegate16 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const) { + return FastDelegate16(x, func); +} + +template +FastDelegate16 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16)) { + return FastDelegate16(func); +} + +//N=17 +template +FastDelegate17 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { + return FastDelegate17(x, func); +} + +template +FastDelegate17 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const) { + return FastDelegate17(x, func); +} + +template +FastDelegate17 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17)) { + return FastDelegate17(func); +} + +//N=18 +template +FastDelegate18 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { + return FastDelegate18(x, func); +} + +template +FastDelegate18 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const) { + return FastDelegate18(x, func); +} + +template +FastDelegate18 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18)) { + return FastDelegate18(func); +} + +//N=19 +template +FastDelegate19 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { + return FastDelegate19(x, func); +} + +template +FastDelegate19 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const) { + return FastDelegate19(x, func); +} + +template +FastDelegate19 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19)) { + return FastDelegate19(func); +} + +//N=20 +template +FastDelegate20 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { + return FastDelegate20(x, func); +} + +template +FastDelegate20 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const) { + return FastDelegate20(x, func); +} + +template +FastDelegate20 MakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20)) { + return FastDelegate20(func); +} -template -FastDelegate MakeDelegate(RetType (*func)(Params... params)) { - return FastDelegate(func); -} // clean up after ourselves... #undef FASTDLGT_RETTYPE diff --git a/utils/mmsource/core/sourcehook/generate/FastDelegate.hxx b/utils/mmsource/core/sourcehook/generate/FastDelegate.hxx new file mode 100644 index 00000000..6f2fe49c --- /dev/null +++ b/utils/mmsource/core/sourcehook/generate/FastDelegate.hxx @@ -0,0 +1,1054 @@ +// FastDelegate.h +// Efficient delegates in C++ that generate only two lines of asm code! +// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp +// +// - Don Clugston, Mar 2004. +// Major contributions were made by Jody Hagins. +// History: +// 24-Apr-04 1.0 * Submitted to CodeProject. +// 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack. +// * Improved syntax for horrible_cast (thanks Paul Bludov). +// * Tested on Metrowerks MWCC and Intel ICL (IA32) +// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL. +// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5 +// * Now works on /clr "managed C++" code on VC7, VC7.1 +// * Comeau C++ now compiles without warnings. +// * Prevent the virtual inheritance case from being used on +// VC6 and earlier, which generate incorrect code. +// * Improved warning and error messages. Non-standard hacks +// now have compile-time checks to make them safer. +// * implicit_cast used instead of static_cast in many cases. +// * If calling a const member function, a const class pointer can be used. +// * MakeDelegate() global helper function added to simplify pass-by-value. +// * Added fastdelegate.clear() +// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates) +// 30-Oct-04 1.3 * Support for (non-void) return values. +// * No more workarounds in client code! +// MSVC and Intel now use a clever hack invented by John Dlugosz: +// - The FASTDELEGATEDECLARE workaround is no longer necessary. +// - No more warning messages for VC6 +// * Less use of macros. Error messages should be more comprehensible. +// * Added include guards +// * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks). +// * Now tested on VS 2005 Express Beta, PGI C++ +// 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates. +// * <,>,<=,>= comparison operators to allow storage in ordered containers. +// * Substantial reduction of code size, especially the 'Closure' class. +// * Standardised all the compiler-specific workarounds. +// * MFP conversion now works for CodePlay (but not yet supported in the full code). +// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1 +// * New syntax: FastDelegate< int (char *, double) >. +// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric). +// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium. +// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())" +// * Fully supported by CodePlay VectorC +// * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC! +// * More optimal assignment,== and != operators for static function pointers. + +#ifndef FASTDELEGATE_H +#define FASTDELEGATE_H + +#ifdef _MSC_VER +# if _MSC_VER > 1000 +# pragma once +# endif // _MSC_VER > 1000 +#endif // #ifdef _MSC_VER + +#include // to allow <,> comparisons + +//////////////////////////////////////////////////////////////////////////////// +// Configuration options +// +//////////////////////////////////////////////////////////////////////////////// + +// Uncomment the following #define for optimally-sized delegates. +// In this case, the generated asm code is almost identical to the code you'd get +// if the compiler had native support for delegates. +// It will not work on systems where sizeof(dataptr) < sizeof(codeptr). +// Thus, it will not work for DOS compilers using the medium model. +// It will also probably fail on some DSP systems. +#define FASTDELEGATE_USESTATICFUNCTIONHACK + +// Uncomment the next line to allow function declarator syntax. +// It is automatically enabled for those compilers where it is known to work. +//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Compiler identification for workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Compiler identification. It's not easy to identify Visual C++ because +// many vendors fraudulently define Microsoft's identifiers. +#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__) +#define FASTDLGT_ISMSVC + +#if (_MSC_VER <1300) // Many workarounds are required for VC6. +#define FASTDLGT_VC6 +#pragma warning(disable:4786) // disable this ridiculous warning +#endif + +#endif + +// Does the compiler uses Microsoft's member function pointer structure? +// If so, it needs special treatment. +// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's +// identifier, _MSC_VER. We need to filter Metrowerks out. +#if defined(_MSC_VER) && !defined(__MWERKS__) +#define FASTDLGT_MICROSOFT_MFP + +#if !defined(__VECTOR_C) +// CodePlay doesn't have the __single/multi/virtual_inheritance keywords +#define FASTDLGT_HASINHERITANCE_KEYWORDS +#endif +#endif + +// Does it allow function declarator syntax? The following compilers are known to work: +#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1 +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use. +#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too. +#if defined (__MWERKS__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +#ifdef __GNUC__ // Workaround GCC bug #8271 + // At present, GCC doesn't recognize constness of MFPs in templates +#define FASTDELEGATE_GCC_BUG_8271 +#endif + + + +//////////////////////////////////////////////////////////////////////////////// +// General tricks used in this code +// +// (a) Error messages are generated by typdefing an array of negative size to +// generate compile-time errors. +// (b) Warning messages on MSVC are generated by declaring unused variables, and +// enabling the "variable XXX is never used" warning. +// (c) Unions are used in a few compiler-specific cases to perform illegal casts. +// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to +// (char *) first to ensure that the correct number of *bytes* are added. +// +//////////////////////////////////////////////////////////////////////////////// +// Helper templates +// +//////////////////////////////////////////////////////////////////////////////// + + +namespace fastdelegate { +namespace detail { // we'll hide the implementation details in a nested namespace. + +// implicit_cast< > +// I believe this was originally going to be in the C++ standard but +// was left out by accident. It's even milder than static_cast. +// I use it instead of static_cast<> to emphasize that I'm not doing +// anything nasty. +// Usage is identical to static_cast<> +template +inline OutputClass implicit_cast(InputClass input){ + return input; +} + +// horrible_cast< > +// This is truly evil. It completely subverts C++'s type system, allowing you +// to cast from any class to any other class. Technically, using a union +// to perform the cast is undefined behaviour (even in C). But we can see if +// it is OK by checking that the union is the same size as each of its members. +// horrible_cast<> should only be used for compiler-specific workarounds. +// Usage is identical to reinterpret_cast<>. + +// This union is declared outside the horrible_cast because BCC 5.5.1 +// can't inline a function with a nested class, and gives a warning. +template +union horrible_union{ + OutputClass out; + InputClass in; +}; + +template +inline OutputClass horrible_cast(const InputClass input){ + horrible_union u; + // Cause a compile-time error if in, out and u are not the same size. + // If the compile fails here, it means the compiler has peculiar + // unions which would prevent the cast from working. + typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) + && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1]; + u.in = input; + return u.out; +} + +//////////////////////////////////////////////////////////////////////////////// +// Workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Backwards compatibility: This macro used to be necessary in the virtual inheritance +// case for Intel and Microsoft. Now it just forward-declares the class. +#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME; + +// Prevent use of the static function hack with the DOS medium model. +#ifdef __MEDIUM__ +#undef FASTDELEGATE_USESTATICFUNCTIONHACK +#endif + +// DefaultVoid - a workaround for 'void' templates in VC6. +// +// (1) VC6 and earlier do not allow 'void' as a default template argument. +// (2) They also doesn't allow you to return 'void' from a function. +// +// Workaround for (1): Declare a dummy type 'DefaultVoid' which we use +// when we'd like to use 'void'. We convert it into 'void' and back +// using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>. +// Workaround for (2): On VC6, the code for calling a void function is +// identical to the code for calling a non-void function in which the +// return value is never used, provided the return value is returned +// in the EAX register, rather than on the stack. +// This is true for most fundamental types such as int, enum, void *. +// Const void * is the safest option since it doesn't participate +// in any automatic conversions. But on a 16-bit compiler it might +// cause extra code to be generated, so we disable it for all compilers +// except for VC6 (and VC5). +#ifdef FASTDLGT_VC6 +// VC6 workaround +typedef const void * DefaultVoid; +#else +// On any other compiler, just use a normal void. +typedef void DefaultVoid; +#endif + +// Translate from 'DefaultVoid' to 'void'. +// Everything else is unchanged +template +struct DefaultVoidToVoid { typedef T type; }; + +template <> +struct DefaultVoidToVoid { typedef void type; }; + +// Translate from 'void' into 'DefaultVoid' +// Everything else is unchanged +template +struct VoidToDefaultVoid { typedef T type; }; + +template <> +struct VoidToDefaultVoid { typedef DefaultVoid type; }; + + + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 1: +// +// Conversion of member function pointer to a standard form +// +//////////////////////////////////////////////////////////////////////////////// + +// GenericClass is a fake class, ONLY used to provide a type. +// It is vitally important that it is never defined, so that the compiler doesn't +// think it can optimize the invocation. For example, Borland generates simpler +// code if it knows the class only uses single inheritance. + +// Compilers using Microsoft's structure need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS + // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP + // (4 bytes), even when the /vmg option is used. Declaring an empty class + // would give 16 byte pointers in this case.... + class __single_inheritance GenericClass; +#endif + // ...but for Codeplay, an empty class *always* gives 4 byte pointers. + // If compiled with the /clr option ("managed C++"), the JIT compiler thinks + // it needs to load GenericClass before it can call any of its functions, + // (compiles OK but crashes at runtime!), so we need to declare an + // empty class to make it happy. + // Codeplay and VC4 can't cope with the unknown_inheritance case either. + class GenericClass {}; +#else + class GenericClass; +#endif + +// The size of a single inheritance member function pointer. +const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)()); + +// SimplifyMemFunc< >::Convert() +// +// A template function that converts an arbitrary member function pointer into the +// simplest possible form of member function pointer, using a supplied 'this' pointer. +// According to the standard, this can be done legally with reinterpret_cast<>. +// For (non-standard) compilers which use member function pointers which vary in size +// depending on the class, we need to use knowledge of the internal structure of a +// member function pointer, as used by the compiler. Template specialization is used +// to distinguish between the sizes. Because some compilers don't support partial +// template specialisation, I use full specialisation of a wrapper struct. + +// general case -- don't know how to convert it. Force a compile failure +template +struct SimplifyMemFunc { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // Unsupported member function type -- force a compile failure. + // (it's illegal to have a array with negative size). + typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100]; + return 0; + } +}; + +// For compilers where all member func ptrs are the same size, everything goes here. +// For non-standard compilers, only single_inheritance classes go here. +template <> +struct SimplifyMemFunc { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { +#if defined __DMC__ + // Digital Mars doesn't allow you to cast between abitrary PMF's, + // even though the standard says you can. The 32-bit compiler lets you + // static_cast through an int, but the DOS compiler doesn't. + bound_func = horrible_cast(function_to_bind); +#else + bound_func = reinterpret_cast(function_to_bind); +#endif + return reinterpret_cast(pthis); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 1b: +// +// Workarounds for Microsoft and Intel +// +//////////////////////////////////////////////////////////////////////////////// + + +// Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay), +// need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +// We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1) +// at the start of each function for extra safety, but VC6 seems to ICE +// intermittently if you do this inside a template. + +// __multiple_inheritance classes go here +// Nasty hack for Microsoft and Intel (IA32 and Itanium) +template<> +struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) > { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // We need to use a horrible_cast to do this conversion. + // In MSVC, a multiple inheritance member pointer is internally defined as: + union { + XFuncType func; + struct { + GenericMemFuncType funcaddress; // points to the actual member function + int delta; // #BYTES to be added to the 'this' pointer + }s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + return reinterpret_cast(reinterpret_cast(pthis) + u.s.delta); + } +}; + +// virtual inheritance is a real nuisance. It's inefficient and complicated. +// On MSVC and Intel, there isn't enough information in the pointer itself to +// enable conversion to a closure pointer. Earlier versions of this code didn't +// work for all cases, and generated a compile-time error instead. +// But a very clever hack invented by John M. Dlugosz solves this problem. +// My code is somewhat different to his: I have no asm code, and I make no +// assumptions about the calling convention that is used. + +// In VC++ and ICL, a virtual_inheritance member pointer +// is internally defined as: +struct MicrosoftVirtualMFP { + void (GenericClass::*codeptr)(); // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtable_index; // or 0 if no virtual inheritance +}; +// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the +// m_codeptr member is *always* called, regardless of the values of the other +// members. (This is *not* true for other compilers, eg GCC, which obtain the +// function address from the vtable if a virtual function is being called). +// Dlugosz's trick is to make the codeptr point to a probe function which +// returns the 'this' pointer that was used. + +// Define a generic class that uses virtual inheritance. +// It has a trival member function that returns the value of the 'this' pointer. +struct GenericVirtualClass : virtual public GenericClass +{ + typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); + GenericVirtualClass * GetThis() { return this; } +}; + +// __virtual_inheritance classes go here +template <> +struct SimplifyMemFunc +{ + + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + union { + XFuncType func; + GenericClass* (X::*ProbeFunc)(); + MicrosoftVirtualMFP s; + } u; + u.func = function_to_bind; + bound_func = reinterpret_cast(u.s.codeptr); + union { + GenericVirtualClass::ProbePtrType virtfunc; + MicrosoftVirtualMFP s; + } u2; + // Check that the horrible_cast<>s will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s) + && sizeof(function_to_bind)==sizeof(u.ProbeFunc) + && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; + // Unfortunately, taking the address of a MF prevents it from being inlined, so + // this next line can't be completely optimised away by the compiler. + u2.virtfunc = &GenericVirtualClass::GetThis; + u.s.codeptr = u2.s.codeptr; + return (pthis->*u.ProbeFunc)(); + } +}; + +#if (_MSC_VER <1300) + +// Nasty hack for Microsoft Visual C++ 6.0 +// unknown_inheritance classes go here +// There is a compiler bug in MSVC6 which generates incorrect code in this case!! +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // There is an apalling but obscure compiler bug in MSVC6 and earlier: + // vtable_index and 'vtordisp' are always set to 0 in the + // unknown_inheritance case! + // This means that an incorrect function could be called!!! + // Compiling with the /vmg option leads to potentially incorrect code. + // This is probably the reason that the IDE has a user interface for specifying + // the /vmg option, but it is disabled - you can only specify /vmg on + // the command line. In VC1.5 and earlier, the compiler would ICE if it ever + // encountered this situation. + // It is OK to use the /vmg option if /vmm or /vms is specified. + + // Fortunately, the wrong function is only called in very obscure cases. + // It only occurs when a derived class overrides a virtual function declared + // in a virtual base class, and the member function + // points to the *Derived* version of that function. The problem can be + // completely averted in 100% of cases by using the *Base class* for the + // member fpointer. Ie, if you use the base class as an interface, you'll + // stay out of trouble. + // Occasionally, you might want to point directly to a derived class function + // that isn't an override of a base class. In this case, both vtable_index + // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated. + // We can generate correct code in this case. To prevent an incorrect call from + // ever being made, on MSVC6 we generate a warning, and call a function to + // make the program crash instantly. + typedef char ERROR_VC6CompilerBug[-100]; + return 0; + } +}; + + +#else + +// Nasty hack for Microsoft and Intel (IA32 and Itanium) +// unknown_inheritance classes go here +// This is probably the ugliest bit of code I've ever written. Look at the casts! +// There is a compiler bug in MSVC6 which prevents it from using this code. +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // The member function pointer is 16 bytes long. We can't use a normal cast, but + // we can use a union to do the conversion. + union { + XFuncType func; + // In VC++ and ICL, an unknown_inheritance member pointer + // is internally defined as: + struct { + GenericMemFuncType m_funcaddress; // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtordisp; // #bytes to add to 'this' to find the vtable + int vtable_index; // or 0 if no virtual inheritance + } s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + int virtual_delta = 0; + if (u.s.vtable_index) { // Virtual inheritance is used + // First, get to the vtable. + // It is 'vtordisp' bytes from the start of the class. + const int * vtable = *reinterpret_cast( + reinterpret_cast(pthis) + u.s.vtordisp ); + + // 'vtable_index' tells us where in the table we should be looking. + virtual_delta = u.s.vtordisp + *reinterpret_cast( + reinterpret_cast(vtable) + u.s.vtable_index); + } + // The int at 'virtual_delta' gives us the amount to add to 'this'. + // Finally we can add the three components together. Phew! + return reinterpret_cast( + reinterpret_cast(pthis) + u.s.delta + virtual_delta); + }; +}; +#endif // MSVC 7 and greater + +#endif // MS/Intel hacks + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 2: +// +// Define the delegate storage, and cope with static functions +// +//////////////////////////////////////////////////////////////////////////////// + +// DelegateMemento -- an opaque structure which can hold an arbitary delegate. +// It knows nothing about the calling convention or number of arguments used by +// the function pointed to. +// It supplies comparison operators so that it can be stored in STL collections. +// It cannot be set to anything other than null, nor invoked directly: +// it must be converted to a specific delegate. + +// Implementation: +// There are two possible implementations: the Safe method and the Evil method. +// DelegateMemento - Safe version +// +// This implementation is standard-compliant, but a bit tricky. +// A static function pointer is stored inside the class. +// Here are the valid values: +// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+ +// | 0 | 0 | 0 | Empty | +// | !=0 |(dontcare)| Invoker | Static function| +// | 0 | !=0 | !=0* | Method call | +// +--------------------+----------+------------+----------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// When stored stored inside a specific delegate, the 'dontcare' entries are replaced +// with a reference to the delegate itself. This complicates the = and == operators +// for the delegate class. + +// DelegateMemento - Evil version +// +// For compilers where data pointers are at least as big as code pointers, it is +// possible to store the function pointer in the this pointer, using another +// horrible_cast. In this case the DelegateMemento implementation is simple: +// +--pThis --+-- pMemFunc-+-- Meaning---------------------+ +// | 0 | 0 | Empty | +// | !=0 | !=0* | Static function or method call| +// +----------+------------+-------------------------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// Note that the Sun C++ and MSVC documentation explicitly state that they +// support static_cast between void * and function pointers. + +class DelegateMemento { +protected: + // the data is protected, not private, because many + // compilers have problems with template friends. + typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP. + detail::GenericClass *m_pthis; + GenericMemFuncType m_pFunction; + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + typedef void (*GenericFuncPtr)(); // arbitrary code pointer + GenericFuncPtr m_pStaticFunction; +#endif + +public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {}; + void clear() { + m_pthis=0; m_pFunction=0; m_pStaticFunction=0; + } +#else + DelegateMemento() : m_pthis(0), m_pFunction(0) {}; + void clear() { m_pthis=0; m_pFunction=0; } +#endif +public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + inline bool IsEqual (const DelegateMemento &x) const{ + // We have to cope with the static function pointers as a special case + if (m_pFunction!=x.m_pFunction) return false; + // the static function ptrs must either both be equal, or both be 0. + if (m_pStaticFunction!=x.m_pStaticFunction) return false; + if (m_pStaticFunction!=0) return m_pthis==x.m_pthis; + else return true; + } +#else // Evil Method + inline bool IsEqual (const DelegateMemento &x) const{ + return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction; + } +#endif + // Provide a strict weak ordering for DelegateMementos. + inline bool IsLess(const DelegateMemento &right) const { + // deal with static function pointers first +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0) + return m_pStaticFunction < right.m_pStaticFunction; +#endif + if (m_pthis !=right.m_pthis) return m_pthis < right.m_pthis; + // There are no ordering operators for member function pointers, + // but we can fake one by comparing each byte. The resulting ordering is + // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers. + return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0; + + } + // BUGFIX (Mar 2005): + // We can't just compare m_pFunction because on Metrowerks, + // m_pFunction can be zero even if the delegate is not empty! + inline bool operator ! () const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } + inline bool empty() const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } +public: + DelegateMemento & operator = (const DelegateMemento &right) { + SetMementoFrom(right); + return *this; + } + inline bool operator <(const DelegateMemento &right) { + return IsLess(right); + } + inline bool operator >(const DelegateMemento &right) { + return right.IsLess(*this); + } + DelegateMemento (const DelegateMemento &right) : + m_pthis(right.m_pthis), m_pFunction(right.m_pFunction) +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + , m_pStaticFunction (right.m_pStaticFunction) +#endif + {} +protected: + void SetMementoFrom(const DelegateMemento &right) { + m_pFunction = right.m_pFunction; + m_pthis = right.m_pthis; +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = right.m_pStaticFunction; +#endif + } +}; + + +// ClosurePtr<> +// +// A private wrapper class that adds function signatures to DelegateMemento. +// It's the class that does most of the actual work. +// The signatures are specified by: +// GenericMemFunc: must be a type of GenericClass member function pointer. +// StaticFuncPtr: must be a type of function pointer with the same signature +// as GenericMemFunc. +// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6 +// where it never returns void (returns DefaultVoid instead). + +// An outer class, FastDelegateN<>, handles the invoking and creates the +// necessary typedefs. +// This class does everything else. + +namespace detail { + +template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr> +class ClosurePtr : public DelegateMemento { +public: + // These functions are for setting the delegate to a member function. + + // Here's the clever bit: we convert an arbitrary member function into a + // standard form. XMemFunc should be a member function of class X, but I can't + // enforce that here. It needs to be enforced by the wrapper class. + template < class X, class XMemFunc > + inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) { + m_pthis = SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(pthis, function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } + // For const member functions, we only need a const class pointer. + // Since we know that the member function is const, it's safe to + // remove the const qualifier from the 'this' pointer with a const_cast. + // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name. + template < class X, class XMemFunc> + inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) { + m_pthis= SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(const_cast(pthis), function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates + template < class X, class XMemFunc> + inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) { + bindconstmemfunc(pthis, function_to_bind); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#endif + // These functions are required for invoking the stored function + inline GenericClass *GetClosureThis() const { return m_pthis; } + inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast(m_pFunction); } + +// There are a few ways of dealing with static function pointers. +// There's a standard-compliant, but tricky method. +// There's also a straightforward hack, that won't work on DOS compilers using the +// medium memory model. It's so evil that I can't recommend it, but I've +// implemented it anyway because it produces very nice asm code. + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + +// ClosurePtr<> - Safe version +// +// This implementation is standard-compliant, but a bit tricky. +// I store the function pointer inside the class, and the delegate then +// points to itself. Whenever the delegate is copied, these self-references +// must be transformed, and this complicates the = and == operators. +public: + // The next two functions are for operator ==, =, and the copy constructor. + // We may need to convert the m_pthis pointers, so that + // they remain as self-references. + template< class DerivedClass > + inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &x) { + SetMementoFrom(x); + if (m_pStaticFunction!=0) { + // transform self references... + m_pthis=reinterpret_cast(pParent); + } + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + template < class DerivedClass, class ParentInvokerSig > + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind ) { + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + bindmemfunc(pParent, static_function_invoker); + } + m_pStaticFunction=reinterpret_cast(function_to_bind); + } + inline UnvoidStaticFuncPtr GetStaticFunction() const { + return reinterpret_cast(m_pStaticFunction); + } +#else + +// ClosurePtr<> - Evil version +// +// For compilers where data pointers are at least as big as code pointers, it is +// possible to store the function pointer in the this pointer, using another +// horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and +// speeds up comparison and assignment. If C++ provided direct language support +// for delegates, they would produce asm code that was almost identical to this. +// Note that the Sun C++ and MSVC documentation explicitly state that they +// support static_cast between void * and function pointers. + + template< class DerivedClass > + inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &right) { + SetMementoFrom(right); + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + // ******** EVIL, EVIL CODE! ******* + template < class DerivedClass, class ParentInvokerSig> + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind) { + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + // We'll be ignoring the 'this' pointer, but we need to make sure we pass + // a valid value to bindmemfunc(). + bindmemfunc(pParent, static_function_invoker); + } + + // WARNING! Evil hack. We store the function in the 'this' pointer! + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1]; + m_pthis = horrible_cast(function_to_bind); + // MSVC, SunC++ and DMC accept the following (non-standard) code: +// m_pthis = static_cast(static_cast(function_to_bind)); + // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long +// m_pthis = reinterpret_cast(reinterpret_cast(function_to_bind)); + } + // ******** EVIL, EVIL CODE! ******* + // This function will be called with an invalid 'this' pointer!! + // We're just returning the 'this' pointer, converted into + // a function pointer! + inline UnvoidStaticFuncPtr GetStaticFunction() const { + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1]; + return horrible_cast(this); + } +#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + + // Does the closure contain this static function? + inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){ + if (funcptr==0) return empty(); + // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary + // value that is not equal to any valid function pointer. + else return funcptr==reinterpret_cast(GetStaticFunction()); + } +}; + + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 3: +// +// Wrapper classes to ensure type safety +// +//////////////////////////////////////////////////////////////////////////////// + + +// Once we have the member function conversion templates, it's easy to make the +// wrapper classes. So that they will work with as many compilers as possible, +// the classes are of the form +// FastDelegate3 +// They can cope with any combination of parameters. The max number of parameters +// allowed is 8, but it is trivial to increase this limit. +// Note that we need to treat const member functions seperately. +// All this class does is to enforce type safety, and invoke the delegate with +// the correct list of parameters. + +// Because of the weird rule about the class of derived member function pointers, +// you sometimes need to apply a downcast to the 'this' pointer. +// This is the reason for the use of "implicit_cast(pthis)" in the code below. +// If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction, +// without this trick you'd need to write: +// MyDelegate(static_cast(&d), &CDerivedClass::SimpleVirtualFunction); +// but with the trick you can write +// MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction); + +// RetType is the type the compiler uses in compiling the template. For VC6, +// it cannot be void. DesiredRetType is the real type which is returned from +// all of the functions. It can be void. + +// Implicit conversion to "bool" is achieved using the safe_bool idiom, +// using member data pointers (MDP). This allows "if (dg)..." syntax +// Because some compilers (eg codeplay) don't have a unique value for a zero +// MDP, an extra padding member is added to the SafeBool struct. +// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so +// in that case the static function constructor is not made explicit; this +// allows "if (dg==0) ..." to compile. + +@VARARGS +template<@CLASSARGS, class RetType=detail::DefaultVoid> +class FastDelegate@NUM { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(@FUNCARGS); + typedef RetType (*UnvoidStaticFunctionPtr)(@FUNCARGS); + typedef RetType (detail::GenericClass::*GenericMemFn)(@FUNCARGS); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate@NUM type; + + // Construction and comparison functions + FastDelegate@NUM() { clear(); } + FastDelegate@NUM(const FastDelegate@NUM &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate@NUM &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate@NUM &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate@NUM &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate@NUM &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate@NUM &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate@NUM(Y *pthis, DesiredRetType (X::* function_to_bind)(@FUNCARGS) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(@FUNCARGS)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate@NUM(const Y *pthis, DesiredRetType (X::* function_to_bind)(@FUNCARGS) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(@FUNCARGS) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate@NUM(DesiredRetType (*function_to_bind)(@FUNCARGS) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(@FUNCARGS) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(@FUNCARGS)) { + m_Closure.bindstaticfunc(this, &FastDelegate@NUM::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (@FUNCARGS) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(@INVOKEARGS); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(@FUNCARGS) const { + return (*(m_Closure.GetStaticFunction()))(@INVOKEARGS); } +}; + +@ENDVAR + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 4: +// +// FastDelegate<> class (Original author: Jody Hagins) +// Allows boost::function style syntax like: +// FastDelegate< double (int, long) > +// instead of: +// FastDelegate2< int, long, double > +// +//////////////////////////////////////////////////////////////////////////////// + +#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +// Declare FastDelegate as a class template. It will be specialized +// later for all number of arguments. +template +class FastDelegate; + +@VARARGS +// Specialization to allow use of +// FastDelegate< R ( @SELARGS ) > +// instead of +// FastDelegate@NUM < @SELARGS, R > +template +class FastDelegate< R ( @SELARGS ) > + // Inherit from FastDelegate@NUM so that it can be treated just like a FastDelegate@NUM + : public FastDelegate@NUM < @SELARGS, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate@NUM < @SELARGS, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( @FUNCARGS )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( @FUNCARGS ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( @FUNCARGS )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +@ENDVAR + +#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 5: +// +// MakeDelegate() helper function +// +// MakeDelegate(&x, &X::func) returns a fastdelegate of the type +// necessary for calling x.func() with the correct number of arguments. +// This makes it possible to eliminate many typedefs from user code. +// +//////////////////////////////////////////////////////////////////////////////// + +// Also declare overloads of a MakeDelegate() global function to +// reduce the need for typedefs. +// We need seperate overloads for const and non-const member functions. +// Also, because of the weird rule about the class of derived member function pointers, +// implicit downcasts may need to be applied later to the 'this' pointer. +// That's why two classes (X and Y) appear in the definitions. Y must be implicitly +// castable to X. + +// Workaround for VC6. VC6 needs void return types converted into DefaultVoid. +// GCC 3.2 and later won't compile this unless it's preceded by 'typename', +// but VC6 doesn't allow 'typename' in this context. +// So, I have to use a macro. + +#ifdef FASTDLGT_VC6 +#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid::type +#else +#define FASTDLGT_RETTYPE RetType +#endif + +@VARARGS +template +FastDelegate@NUM<@SELARGS, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(@FUNCARGS)) { + return FastDelegate@NUM<@SELARGS, FASTDLGT_RETTYPE>(x, func); +} + +template +FastDelegate@NUM<@SELARGS, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(@FUNCARGS) const) { + return FastDelegate@NUM<@SELARGS, FASTDLGT_RETTYPE>(x, func); +} + +template <@CLASSARGS, class RetType> +FastDelegate@NUM<@SELARGS, FASTDLGT_RETTYPE> MakeDelegate(RetType (*func)(@FUNCARGS)) { + return FastDelegate@NUM<@SELARGS, FASTDLGT_RETTYPE>(func); +} + +@ENDVAR + + // clean up after ourselves... +#undef FASTDLGT_RETTYPE + +} // namespace fastdelegate + +#endif // !defined(FASTDELEGATE_H) diff --git a/utils/mmsource/core/sourcehook/generate/generate b/utils/mmsource/core/sourcehook/generate/generate index 399784cc..044118de 100644 --- a/utils/mmsource/core/sourcehook/generate/generate +++ b/utils/mmsource/core/sourcehook/generate/generate @@ -5,5 +5,7 @@ make cd .. shworker/bin/shworker.bin iter sourcehook.hxx sourcehook.h $1 +shworker/bin/shworker.bin iter sh_memfuncinfo.hxx sh_memfuncinfo.h $1 +shworker/bin/shworker.bin hopter FastDelegate.hxx FastDelegate.h $1 cp *.h .. diff --git a/utils/mmsource/core/sourcehook/generate/generate.bat b/utils/mmsource/core/sourcehook/generate/generate.bat index 82a8c51e..53c863ae 100644 --- a/utils/mmsource/core/sourcehook/generate/generate.bat +++ b/utils/mmsource/core/sourcehook/generate/generate.bat @@ -4,5 +4,7 @@ shworker iter sourcehook.hxx sourcehook.h %1 +shworker iter sh_memfuncinfo.hxx sh_memfuncinfo.h %1 +shworker hopter FastDelegate.hxx FastDelegate.h %1 -copy *.h .. +copy *.h .. \ No newline at end of file diff --git a/utils/mmsource/core/sourcehook/generate/sh_memfuncinfo.hxx b/utils/mmsource/core/sourcehook/generate/sh_memfuncinfo.hxx new file mode 100644 index 00000000..086a25db --- /dev/null +++ b/utils/mmsource/core/sourcehook/generate/sh_memfuncinfo.hxx @@ -0,0 +1,332 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2010 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +/** + * @brief This file provides a way for getting information about a member function. + * @file sh_memfuncinfo.h + */ + +#ifndef __SHINT_MEMFUNC_INFO_H__ +#define __SHINT_MEMFUNC_INFO_H__ + +namespace SourceHook +{ + + // Don Clugston: + // implicit_cast< > + // I believe this was originally going to be in the C++ standard but + // was left out by accident. It's even milder than static_cast. + // I use it instead of static_cast<> to emphasize that I'm not doing + // anything nasty. + // Usage is identical to static_cast<> + template + inline OutputClass implicit_cast(InputClass input){ + return input; + } + + + struct MemFuncInfo + { + bool isVirtual; // Is the function virtual? + int thisptroffs; // The this pointer the function expects to be called with + // If -1, you need to call the GetFuncInfo_GetThisPtr function + int vtblindex; // The function's index in the vtable (0-based, 1=second entry, 2=third entry, ...) + int vtbloffs; // The vtable pointer + }; + + // Ideas by Don Clugston. + // Check out his excellent paper: http://www.codeproject.com/cpp/FastDelegate.asp + + template struct MFI_Impl + { + template static inline void GetFuncInfo(MFP *mfp, MemFuncInfo &out) + { + static char weird_memfunc_pointer_exclamation_mark_arrow_error[N-1000]; + } + }; + +# if SH_COMP == SH_COMP_GCC + + template<> struct MFI_Impl<2*SH_PTRSIZE> // All of these have size==8/16 + { + struct GCC_MemFunPtr + { + union + { + void *funcadr; // always even + intptr_t vtable_index_plus1; // = vindex+1, always odd + }; + intptr_t delta; + }; + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + GCC_MemFunPtr *mfp_detail = (GCC_MemFunPtr*)&mfp; + out.thisptroffs = mfp_detail->delta; + if (mfp_detail->vtable_index_plus1 & 1) + { + out.vtblindex = (mfp_detail->vtable_index_plus1 - 1) / SH_PTRSIZE; + out.vtbloffs = 0; + out.isVirtual = true; + } + else + out.isVirtual = false; + } + }; + +# elif SH_COMP == SH_COMP_MSVC + + namespace + { + int MFI_GetVtblOffset(void *mfp) + { + unsigned char *addr = (unsigned char*)mfp; + if (*addr == 0xE9) // Jmp + { + // May or may not be! + // Check where it'd jump + addr += 5 /*size of the instruction*/ + *(unsigned long*)(addr + 1); + } + + // Check whether it's a virtual function call + // They look like this: + // 004125A0 8B 01 mov eax,dword ptr [ecx] + // 004125A2 FF 60 04 jmp dword ptr [eax+4] + // ==OR== + // 00411B80 8B 01 mov eax,dword ptr [ecx] + // 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h] + + // However, for vararg functions, they look like this: + // 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4] + // 0048F0B4 8B 00 mov eax,dword ptr [eax] + // 0048F0B6 FF 60 08 jmp dword ptr [eax+8] + // ==OR== + // 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4] + // 0048F0B4 8B 00 mov eax,dword ptr [eax] + // 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h] + + // With varargs, the this pointer is passed as if it was the first argument + + bool ok = false; + if (addr[0] == 0x8B && addr[1] == 0x44 && addr[2] == 0x24 && addr[3] == 0x04 && + addr[4] == 0x8B && addr[5] == 0x00) + { + addr += 6; + ok = true; + } + else if (addr[0] == 0x8B && addr[1] == 0x01) + { + addr += 2; + ok = true; + } + if (!ok) + return -1; + + if (*addr++ == 0xFF) + { + if (*addr == 0x60) + { + return *++addr / 4; + } + else if (*addr == 0xA0) + { + return *((unsigned int*)++addr) / 4; + } + else if (*addr == 0x20) + return 0; + else + return -1; + } + return -1; + } + } + + template<> struct MFI_Impl<1*SH_PTRSIZE> // simple ones + { + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + out.thisptroffs = 0; + out.vtbloffs = 0; + } + }; + + template<> struct MFI_Impl<2*SH_PTRSIZE> // more complicated ones! + { + struct MSVC_MemFunPtr2 + { + void *funcadr; + int delta; + }; + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + out.thisptroffs = reinterpret_cast(&mfp)->delta; + out.vtbloffs = 0; + } + }; + + // By Don Clugston, adapted + template<> struct MFI_Impl<3*SH_PTRSIZE> // WOW IT"S GETTING BIGGER OMGOMOGMG + { + class __single_inheritance GenericClass; + class GenericClass {}; + + struct MicrosoftVirtualMFP { + void (GenericClass::*codeptr)(); // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtable_index; // or 0 if no virtual inheritance + }; + + struct GenericVirtualClass : virtual public GenericClass + { + typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); + GenericVirtualClass * GetThis() { return this; } + }; + + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + // This pointer + /* + union { + MFP func; + GenericClass* (T::*ProbeFunc)(); + MicrosoftVirtualMFP s; + } u; + u.func = mfp; + union { + GenericVirtualClass::ProbePtrType virtfunc; + MicrosoftVirtualMFP s; + } u2; + + // Check that the horrible_cast<>s will work + typedef int ERROR_CantUsehorrible_cast[sizeof(mfp)==sizeof(u.s) + && sizeof(mfp)==sizeof(u.ProbeFunc) + && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; + // Unfortunately, taking the address of a MF prevents it from being inlined, so + // this next line can't be completely optimised away by the compiler. + u2.virtfunc = &GenericVirtualClass::GetThis; + u.s.codeptr = u2.s.codeptr; + out.thisptroffs = (reinterpret_cast(NULL)->*u.ProbeFunc)(); + */ + out.thisptroffs = -1; + out.vtbloffs = 0; + } + }; + + // Don: Nasty hack for Microsoft and Intel (IA32 and Itanium) + // unknown_inheritance classes go here + // This is probably the ugliest bit of code I've ever written. Look at the casts! + // There is a compiler bug in MSVC6 which prevents it from using this code. + template<> struct MFI_Impl<4*SH_PTRSIZE> // THE BIGGEST ONE!!!1GABEN + { + template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) + { + out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); + out.isVirtual = out.vtblindex >= 0 ? true : false; + + // The member function pointer is 16 bytes long. We can't use a normal cast, but + // we can use a union to do the conversion. + union { + MFP func; + // In VC++ and ICL, an unknown_inheritance member pointer + // is internally defined as: + struct { + void *m_funcaddress; // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtordisp; // #bytes to add to 'this' to find the vtable + int vtable_index; // or 0 if no virtual inheritance + } s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(u.func)==sizeof(u.s)? 1 : -1]; + u.func = mfp; + int virtual_delta = 0; + if (u.s.vtable_index) { // Virtual inheritance is used + /* + // First, get to the vtable. + // It is 'vtordisp' bytes from the start of the class. + int * vtable = *reinterpret_cast( + reinterpret_cast(thisptr) + u.s.vtordisp ); + + // 'vtable_index' tells us where in the table we should be looking. + virtual_delta = u.s.vtordisp + *reinterpret_cast( + reinterpret_cast(vtable) + u.s.vtable_index); + // The int at 'virtual_delta' gives us the amount to add to 'this'. + // Finally we can add the three components together. Phew! + out.thisptr = reinterpret_cast( + reinterpret_cast(thisptr) + u.s.delta + virtual_delta); + */ + out.vtbloffs = u.s.vtordisp; + out.thisptroffs = -1; + } + else + { + out.vtbloffs = out.vtblindex < 0 ? 0 : u.s.delta; + out.thisptroffs = u.s.delta; + } + }; + }; +# else +# error Unsupported compiler +# endif + + // This version does not take a this pointer + // Useful for hookdecls, as they ensure that mfp is correct through a static_cast + template inline void GetFuncInfo(X mfp, MemFuncInfo &out) + { + MFI_Impl::GetFuncInfo(mfp, out); + } + + // Versions which do take a this +@[$1,0,$a: + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(@[$2,1,$1|, :Param$2@]), MemFuncInfo &out) + { + RetType(Y::*mfp2)(@[$2,1,$1|, :Param$2@]) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(@[$2,1,$1|, :Param$2@]) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(@[$2,1,$1|, :Param$2@]) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } +@] + + // GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it +#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300 + +@[$1,0,$a: + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + +@] + +#endif + +} + +#endif diff --git a/utils/mmsource/core/sourcehook/generate/sourcehook.hxx b/utils/mmsource/core/sourcehook/generate/sourcehook.hxx index e69dd4ea..921942cc 100644 --- a/utils/mmsource/core/sourcehook/generate/sourcehook.hxx +++ b/utils/mmsource/core/sourcehook/generate/sourcehook.hxx @@ -1072,124 +1072,12 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) buf[sizeof(buf) - 1] = 0; \ va_end(ap); -// Helper for MANUALEXTERN. -# define SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); - -// Helpers for transforming X(__VA_ARGS__, Y) -> Y when __VA_ARGS__ is empty. -#define SHINT_COLLAPSE0(_T, ...) __VA_ARGS__ - -// -// MSVC will automatically remove a trailing comma if __VA_ARGS__ is empty. GCC requires using ## to do this. -// -#if defined(_MSC_VER) -# define SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ - fastdelegate::FastDelegate handler); - -# define SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, __VA_ARGS__) - -# define SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, __VA_ARGS__, const char *) - -# define SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, __VA_ARGS__, const char *) - -// Helpers for MANUALEXTERN. -# define SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ...) \ - int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ - fastdelegate::FastDelegate handler); \ - void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); - -# define SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, __VA_ARGS__) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(__VA_ARGS__); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, __VA_ARGS__, const char *) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(SHINT_COLLAPSE0(void, __VA_ARGS__, const char *, ...)); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SH_DECL_MANUALEXTERN(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, __VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -# define SH_DECL_MANUALEXTERN_void(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, void, __VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_void_vafmt(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, void, __VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, __VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -// -// GCC Implementation. -// -#else -# define SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ - fastdelegate::FastDelegate handler); - -# define SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, ##__VA_ARGS__) - -# define SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, ##__VA_ARGS__, const char *) - -# define SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, ##__VA_ARGS__, const char *) - -// Helpers for MANUALEXTERN. -# define SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ...) \ - int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ - fastdelegate::FastDelegate handler); \ - void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); - -# define SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ##__VA_ARGS__) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(__VA_ARGS__); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ##__VA_ARGS__, const char *) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(SHINT_COLLAPSE0(void, ##__VA_ARGS__, const char *, ...)); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SH_DECL_MANUALEXTERN(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, ##__VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -# define SH_DECL_MANUALEXTERN_void(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, void, ##__VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_void_vafmt(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, void, ##__VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, ##__VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -#endif - -// Compatibility wrappers around modern variadic macros. @[$1,0,$a: // ********* Support for $1 arguments ********* #define SH_DECL_HOOK$1(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1:, param$2@]) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]@[$1!=0:, @]rettype> FD; \ MAKE_DELEG(rettype, (@[$2,1,$1|, :param$2 p$2@]), (@[$2,1,$1|, :p$2@])); \ virtual rettype Func(@[$2,1,$1|, :param$2 p$2@]) \ { SH_HANDLEFUNC((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@]), rettype); } \ @@ -1202,12 +1090,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN$1(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1:, param$2@]) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1|:, param$2@]) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]@[$1!=0:, @]rettype> handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]@[$1!=0:, @]rettype> handler); #define SH_DECL_HOOK$1_void(ifacetype, ifacefunc, attr, overload@[$2,1,$1:, param$2@]) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]> FD; \ MAKE_DELEG_void((@[$2,1,$1|, :param$2 p$2@]), (@[$2,1,$1|, :p$2@])); \ virtual void Func(@[$2,1,$1|, :param$2 p$2@]) \ { SH_HANDLEFUNC_void((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@])); } \ @@ -1220,12 +1111,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN$1_void(ifacetype, ifacefunc, attr, overload@[$2,1,$1:, param$2@]) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload@[$1!=0:, @]@[$2,1,$1|, :param$2@]) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]> handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]> handler); #define SH_DECL_HOOK$1_vafmt(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1:, param$2@]) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate@($1+1)<@[$2,1,$1|, :param$2@]@[$1!=0:, @]const char *, rettype> FD; \ MAKE_DELEG(rettype, (@[$2,1,$1|, :param$2 p$2@]@[$1!=0:, @]const char *px), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]px)); \ virtual rettype Func(@[$2,1,$1|, :param$2 p$2@] @[$1!=0:, @]const char *fmt, ...) \ { \ @@ -1241,12 +1135,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN$1_vafmt(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1:, param$2@]) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype@[$1!=0:, @]@[$2,1,$1|, :param$2@]) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate@($1+1)<@[$2,1,$1|, :param$2@]@[$1!=0:, @]const char *, rettype> handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate@($1+1)<@[$2,1,$1|, :param$2@]@[$1!=0:, @]const char *, rettype> handler); #define SH_DECL_HOOK$1_void_vafmt(ifacetype, ifacefunc, attr, overload@[$2,1,$1:, param$2@]) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate@($1+1)<@[$2,1,$1|, :param$2@]@[$1!=0:, @]const char *> FD; \ MAKE_DELEG_void((@[$2,1,$1|, :param$2 p$2@]@[$1!=0:, @]const char *px), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]px)); \ virtual void Func(@[$2,1,$1|, :param$2 p$2@]@[$1!=0:, @]const char *fmt, ...) \ { \ @@ -1262,16 +1159,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN$1_void_vafmt(ifacetype, ifacefunc, attr, overload@[$2,1,$1:, param$2@]) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload@[$1!=0:, @]@[$2,1,$1|, :param$2@]) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate@($1+1)<@[$2,1,$1|, :param$2@]@[$1!=0:, @]const char *> handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate@($1+1)<@[$2,1,$1|, :param$2@]@[$1!=0:, @]const char *> handler); #define SH_DECL_MANUALHOOK$1(hookname, vtblidx, vtbloffs, thisptroffs, rettype@[$2,1,$1:, param$2@]) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]@[$1!=0:, @]rettype> FD; \ MAKE_DELEG(rettype, (@[$2,1,$1|, :param$2 p$2@]), (@[$2,1,$1|, :p$2@])); \ virtual rettype Func(@[$2,1,$1|, :param$2 p$2@]) \ { SH_HANDLEFUNC((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@]), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(@[$2,1,$1|, :param$2@]); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype@[$2,1,$1:, param$2@] > CallEC; \ + typedef SourceHook::ExecutableClass$1< ::SourceHook::EmptyClass, ECMFP, rettype@[$2,1,$1:, param$2@] > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -1285,11 +1185,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN$1(hookname, rettype@[$2,1,$1:, param$2@]) \ - SH_DECL_MANUALEXTERN(hookname, rettype@[$2,1,$1|:, param$2@]) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate$1<@[$2,1,$1:param$2, @]rettype> handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate$1<@[$2,1,$1:param$2, @]rettype> handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(@[$2,1,$1|, :param$2@]); \ + SourceHook::ExecutableClass$1 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK$1_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype@[$2,1,$1:, param$2@]) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate@($1+1)<@[$2,1,$1:param$2, @]const char *, rettype> FD; \ MAKE_DELEG(rettype, (@[$2,1,$1:param$2 p$2, @]const char *px), (@[$2,1,$1:p$2, @]px)); \ virtual rettype Func(@[$2,1,$1:param$2 p$2, @]const char *fmt, ...) \ { \ @@ -1297,7 +1204,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((@[$2,1,$1:param$2, @]const char *, ...), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]"%s", buf), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(@[$2,1,$1:param$2, @]const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype@[$2,1,$1:, param$2@], const char * > CallEC; \ + typedef SourceHook::ExecutableClass@($1+1)< ::SourceHook::EmptyClass, ECMFP, rettype@[$2,1,$1:, param$2@], const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -1311,16 +1218,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN$1_vafmt(hookname, rettype@[$2,1,$1:, param$2@]) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype@[$1!=0:, @]@[$2,1,$1|, :param$2@]) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate@($1+1)<@[$2,1,$1:param$2, @]const char *, rettype> handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate@($1+1)<@[$2,1,$1:param$2, @]const char *, rettype> handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(@[$2,1,$1:param$2, @]const char *, ...); \ + SourceHook::ExecutableClass@($1+1) __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK$1_void(hookname, vtblidx, vtbloffs, thisptroffs@[$2,1,$1:, param$2@]) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]> FD; \ MAKE_DELEG_void((@[$2,1,$1|, :param$2 p$2@]), (@[$2,1,$1|, :p$2@])); \ virtual void Func(@[$2,1,$1|, :param$2 p$2@]) \ { SH_HANDLEFUNC_void((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@])); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(@[$2,1,$1|, :param$2@]); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass$1 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}@[$2,1,$1:, __SH_GPI(param$2)@] }; \ @@ -1329,11 +1243,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN$1_void(hookname@[$2,1,$1:, param$2@]) \ - SH_DECL_MANUALEXTERN_void(hookname@[$1!=0:, @]@[$2,1,$1|, :param$2@]) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]> handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]> handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(@[$2,1,$1|, :param$2@]); \ + SourceHook::ExecutableClass$1 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK$1_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs@[$2,1,$1:, param$2@]) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate@($1+1)<@[$2,1,$1:param$2, @]const char *> FD; \ MAKE_DELEG_void((@[$2,1,$1:param$2 p$2, @]const char *px), (@[$2,1,$1:p$2, @]px)); \ virtual void Func(@[$2,1,$1:param$2 p$2, @]const char *fmt, ...) \ { \ @@ -1341,7 +1261,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((@[$2,1,$1:param$2, @]const char *, ...), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]"%s", buf), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(@[$2,1,$1:param$2, @]const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void@[$2,1,$1:, param$2@], const char * > CallEC; \ + typedef SourceHook::ExecutableClass@($1+1)< ::SourceHook::EmptyClass, ECMFP, void@[$2,1,$1:, param$2@], const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}@[$2,1,$1:, __SH_GPI(param$2)@] }; \ @@ -1350,79 +1270,81 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN$1_void_vafmt(hookname@[$2,1,$1:, param$2@]) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname@[$1!=0:, @]@[$2,1,$1|, :param$2@]) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate@($1+1)<@[$2,1,$1:param$2, @]const char *> handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate@($1+1)<@[$2,1,$1:param$2, @]const char *> handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(@[$2,1,$1:param$2, @]const char *, ...); \ + SourceHook::ExecutableClass@($1+1) __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); @] ////////////////////////////////////////////////////////////////////////// // SH_CALL +#define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \ +{ \ + using namespace ::SourceHook; \ + \ + m_pSH->SetIgnoreHooks(m_VfnPtr); \ + RetType tmpret = (m_ThisPtr->*m_MFP)call; \ + m_pSH->ResetIgnoreHooks(m_VfnPtr); \ + return tmpret; \ +} + +#define SH_MAKE_EXECUTABLECLASS_OB_void(call, prms) \ +{ \ + using namespace ::SourceHook; \ + \ + m_pSH->SetIgnoreHooks(m_VfnPtr); \ + (m_ThisPtr->*m_MFP)call; \ + m_pSH->ResetIgnoreHooks(m_VfnPtr); \ +} + namespace SourceHook { - template - class ExecutableClassN +@[$1,0,$a: + // Support for $1 arguments + template class ExecutableClass$1 { ObjType *m_ThisPtr; void *m_VfnPtr; MFPType m_MFP; ISourceHook *m_pSH; public: - ExecutableClassN(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) - : m_ThisPtr(tp), - m_VfnPtr(vp), - m_MFP(mfp), - m_pSH(pSH) - { } - - RetType operator()(Params... params) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - RetType tmpret = (m_ThisPtr->*m_MFP)(params...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - return tmpret; - } - - template - RetType operator()(Params... params, MoreParams... more) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - RetType tmpret = (m_ThisPtr->*m_MFP)(params..., more...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - return tmpret; - } + ExecutableClass$1(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(@[$2,1,$1|, :Param$2 p$2@]) const + SH_MAKE_EXECUTABLECLASS_OB((@[$2,1,$1|, :p$2@]), (@[$2,1,$1|, :Param$2@])) + + @[$2,$1+1,$a: + template <@[$3,$1+1,$2|, :class Param$3@]> RetType operator()(@[$3,1,$2|, :Param$3 p$3@]) const + SH_MAKE_EXECUTABLECLASS_OB((@[$3,1,$2|, :p$3@]), (@[$3,1,$2|, :Param$3@])) + @] }; - template - class ExecutableClassN + template class ExecutableClass$1 { ObjType *m_ThisPtr; void *m_VfnPtr; MFPType m_MFP; ISourceHook *m_pSH; public: - ExecutableClassN(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) - : m_ThisPtr(tp), - m_VfnPtr(vp), - m_MFP(mfp), - m_pSH(pSH) - { } - - void operator()(Params... params) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - (m_ThisPtr->*m_MFP)(params...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - } - - template - void operator()(Params... params, MoreParams... more) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - (m_ThisPtr->*m_MFP)(params..., more...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - } + ExecutableClass$1(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(@[$2,1,$1|, :Param$2 p$2@]) const + SH_MAKE_EXECUTABLECLASS_OB_void((@[$2,1,$1|, :p$2@]), (@[$2,1,$1|, :Param$2@])) + + @[$2,$1+1,$a: + template <@[$3,$1+1,$2|, :class Param$3@]> void operator()(@[$3,1,$2|, :Param$3 p$3@]) const + SH_MAKE_EXECUTABLECLASS_OB_void((@[$3,1,$2|, :p$3@]), (@[$3,1,$2|, :Param$3@])) + @] }; +@] + } #define SH__CALL_GET_VFNPTR_NORMAL \ @@ -1443,60 +1365,66 @@ namespace SourceHook // That's why SH_CALL takes two parameters: "mfp2" of type RetType(X::*mfp)(params), and "mfp" of type MFP // The only purpose of the mfp2 parameter is to extract the return type -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params...), SourceHook::ISourceHook *shptr) +@[$1,0,$a: +// Support for $1 arguments +template +SourceHook::ExecutableClass$1 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]), SourceHook::ISourceHook *shptr) { SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); + return SourceHook::ExecutableClass$1(ptr, mfp, vfnptr, shptr); } -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params..., ...), SourceHook::ISourceHook *shptr) +template +SourceHook::ExecutableClass$1 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@])const, SourceHook::ISourceHook *shptr) { SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); + return SourceHook::ExecutableClass$1(ptr, mfp, vfnptr, shptr); } -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params...)const, SourceHook::ISourceHook *shptr) +template +SourceHook::ExecutableClass$1 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) { - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass$1( + reinterpret_cast(ptr), mfp, vfnptr, shptr); } +@] + +#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300 +// GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params..., ...)const, SourceHook::ISourceHook *shptr) +@[$1,0,$a: +// Support for $1 arguments +template +SourceHook::ExecutableClass$1 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...), SourceHook::ISourceHook *shptr) { SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); + return SourceHook::ExecutableClass$1(ptr, mfp, vfnptr, shptr); } -template -SourceHook::ExecutableClassN -SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params...), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +template +SourceHook::ExecutableClass$1 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...)const, SourceHook::ISourceHook *shptr) { - SH__CALL_GET_VFNPTR_MANUAL - return SourceHook::ExecutableClassN( - reinterpret_cast(ptr), mfp, vfnptr, shptr); + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass$1(ptr, mfp, vfnptr, shptr); } -template -SourceHook::ExecutableClassN -SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params..., ...), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_MANUAL - return SourceHook::ExecutableClassN( - reinterpret_cast(ptr), mfp, vfnptr, shptr); -} +@] + +#endif #define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp), SH_GLOB_SHPTR) #define SH_MCALL2(ptr, mfp, vtblidx, vtbloffs, thisptroffs) SH_MCALL3((ptr), (mfp), (mfp), (vtblidx), (vtbloffs), (thisptroffs), SH_GLOB_SHPTR) #define SH_MCALL(ptr, mhookname) __SoureceHook_FHM_SHCall##mhookname(ptr) +#undef SH_MAKE_EXECUTABLECLASS_OB +#undef SH_MAKE_EXECUTABLECLASS_OB_void + ////////////////////////////////////////////////////////////////////////// // SetOverrideRet and RecallGetIface for recalls // These take a ISourceHook pointer instead of using SH_GLOB_SHPTR directly @@ -1536,30 +1464,31 @@ namespace SourceHook { return OverrideFunctor(); } - - template - OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Params...)) +@[$1,0,$a: + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(@[$2,1,$1|, :Param$2@])) { return OverrideFunctor(); } - template - OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Params..., ...)) + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(@[$2,1,$1:Param$2, @]...)) { return OverrideFunctor(); } - template - Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Params...)) + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(@[$2,1,$1|, :Param$2@])) { return reinterpret_cast(shptr->GetIfacePtr()); } - template - Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Params..., ...)) + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(@[$2,1,$1:Param$2, @]...)) { return reinterpret_cast(shptr->GetIfacePtr()); } +@] } #endif diff --git a/utils/mmsource/core/sourcehook/sh_memfuncinfo.h b/utils/mmsource/core/sourcehook/sh_memfuncinfo.h index f83bf69b..9c0020c1 100644 --- a/utils/mmsource/core/sourcehook/sh_memfuncinfo.h +++ b/utils/mmsource/core/sourcehook/sh_memfuncinfo.h @@ -125,11 +125,6 @@ namespace SourceHook addr += 2; ok = true; } - else if (addr[0] == 0x48 && addr[1] == 0x8B && addr[2] == 0x01) - { - addr += 3; - ok = true; - } if (!ok) return -1; @@ -137,11 +132,11 @@ namespace SourceHook { if (*addr == 0x60) { - return *++addr / SH_PTRSIZE; + return *++addr / 4; } else if (*addr == 0xA0) { - return *((unsigned int*)++addr) / SH_PTRSIZE; + return *((unsigned int*)++addr) / 4; } else if (*addr == 0x20) return 0; @@ -294,34 +289,624 @@ namespace SourceHook } // Versions which do take a this - // - template - inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Params...), MemFuncInfo &out) + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(), MemFuncInfo &out) + { + RetType(Y::*mfp2)() = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)() const, MemFuncInfo &out) + { + RetType(Y::*mfp2)() const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + // GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it +#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300 + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...) const, MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...) const = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...) const, MemFuncInfo &out) { - RetType(Y::*mfp2)(Params...) = mfp; + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } - template - inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Params...) const, MemFuncInfo &out) + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...), MemFuncInfo &out) + { + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...) = mfp; + MFI_Impl::GetFuncInfo(mfp2, out); + } + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...) const, MemFuncInfo &out) { - RetType(Y::*mfp2)(Params...) const = mfp; + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } - template - inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Params..., ...), MemFuncInfo &out) + + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...), MemFuncInfo &out) { - RetType(Y::*mfp2)(Params..., ...) = mfp; + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } - template - inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Params..., ...) const, MemFuncInfo &out) + template + inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...) const, MemFuncInfo &out) { - RetType(Y::*mfp2)(Params..., ...) const = mfp; + RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } + + + +#endif + } #endif diff --git a/utils/mmsource/core/sourcehook/sh_memory.h b/utils/mmsource/core/sourcehook/sh_memory.h index bd36e79d..9ffa1fb2 100644 --- a/utils/mmsource/core/sourcehook/sh_memory.h +++ b/utils/mmsource/core/sourcehook/sh_memory.h @@ -129,20 +129,13 @@ namespace SourceHook #elif SH_SYS == SH_SYS_APPLE vm_size_t ignoreSize; vm_address_t vmaddr = (vm_address_t)addr; - memory_object_name_t obj; -#if defined(__i386__) vm_region_basic_info_data_t info; vm_region_flavor_t flavor = VM_REGION_BASIC_INFO; + memory_object_name_t obj; + mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT; kern_return_t kr = vm_region(mach_task_self(), &vmaddr, &ignoreSize, flavor, (vm_region_info_t)&info, &count, &obj); -#elif defined(__x86_64__) - vm_region_basic_info_data_64_t info; - vm_region_flavor_t flavor = VM_REGION_BASIC_INFO_64; - mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; - kern_return_t kr = vm_region_64(mach_task_self(), &vmaddr, &ignoreSize, flavor, - (vm_region_info_64_t)&info, &count, &obj); -#endif if (kr != KERN_SUCCESS) return false; *bits = 0; @@ -255,7 +248,7 @@ namespace SourceHook */ namespace { - static inline bool ModuleInMemory(char *addr, size_t len) + bool ModuleInMemory(char *addr, size_t len) { #if SH_SYS == SH_SYS_LINUX // On linux, first check /proc/self/maps @@ -333,7 +326,6 @@ namespace SourceHook for (size_t i = 0; i < len; i++) dummy = p[i]; - (void)dummy; // silence unused var, we must read from p g_BadReadCalled = false; @@ -341,7 +333,7 @@ namespace SourceHook return false; #elif SH_SYS == SH_SYS_APPLE - struct sigaction sa, osa, osa2; + struct sigaction sa, osa; sa.sa_sigaction = BadReadHandler; sa.sa_flags = SA_SIGINFO | SA_RESTART; @@ -352,20 +344,16 @@ namespace SourceHook if (sigaction(SIGBUS, &sa, &osa) == -1) return false; - if (sigaction(SIGSEGV, &sa, &osa2) == -1) - return false; volatile const char *p = reinterpret_cast(addr); char dummy; for (size_t i = 0; i < len; i++) dummy = p[i]; - (void)dummy; // silence unused var, we must read from p g_BadReadCalled = false; sigaction(SIGBUS, &osa, NULL); - sigaction(SIGSEGV, &osa2, NULL); return true; #elif SH_XP == SH_XP_WINAPI diff --git a/utils/mmsource/core/sourcehook/sourcehook.h b/utils/mmsource/core/sourcehook/sourcehook.h index 1c008ff1..33fdd658 100644 --- a/utils/mmsource/core/sourcehook/sourcehook.h +++ b/utils/mmsource/core/sourcehook/sourcehook.h @@ -1072,124 +1072,12 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) buf[sizeof(buf) - 1] = 0; \ va_end(ap); -// Helper for MANUALEXTERN. -# define SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); - -// Helpers for transforming X(__VA_ARGS__, Y) -> Y when __VA_ARGS__ is empty. -#define SHINT_COLLAPSE0(_T, ...) __VA_ARGS__ - -// -// MSVC will automatically remove a trailing comma if __VA_ARGS__ is empty. GCC requires using ## to do this. -// -#if defined(_MSC_VER) -# define SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ - fastdelegate::FastDelegate handler); - -# define SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, __VA_ARGS__) - -# define SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, __VA_ARGS__, const char *) - -# define SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, __VA_ARGS__, const char *) - -// Helpers for MANUALEXTERN. -# define SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ...) \ - int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ - fastdelegate::FastDelegate handler); \ - void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); - -# define SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, __VA_ARGS__) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(__VA_ARGS__); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, __VA_ARGS__, const char *) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(SHINT_COLLAPSE0(void, __VA_ARGS__, const char *, ...)); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SH_DECL_MANUALEXTERN(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, __VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -# define SH_DECL_MANUALEXTERN_void(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, void, __VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_void_vafmt(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, void, __VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, __VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -// -// GCC Implementation. -// -#else -# define SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ - fastdelegate::FastDelegate handler); - -# define SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, ##__VA_ARGS__) - -# define SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, ##__VA_ARGS__, const char *) - -# define SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, ##__VA_ARGS__, const char *) - -// Helpers for MANUALEXTERN. -# define SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ...) \ - int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ - fastdelegate::FastDelegate handler); \ - void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); - -# define SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ##__VA_ARGS__) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(__VA_ARGS__); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ##__VA_ARGS__, const char *) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(SHINT_COLLAPSE0(void, ##__VA_ARGS__, const char *, ...)); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SH_DECL_MANUALEXTERN(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, ##__VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -# define SH_DECL_MANUALEXTERN_void(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, void, ##__VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_void_vafmt(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, void, ##__VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, ##__VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -#endif - -// Compatibility wrappers around modern variadic macros. // ********* Support for 0 arguments ********* #define SH_DECL_HOOK0(ifacetype, ifacefunc, attr, overload, rettype) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate0 FD; \ MAKE_DELEG(rettype, (), ()); \ virtual rettype Func() \ { SH_HANDLEFUNC((), (), rettype); } \ @@ -1202,12 +1090,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN0(ifacetype, ifacefunc, attr, overload, rettype) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate0 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate0 handler); #define SH_DECL_HOOK0_void(ifacetype, ifacefunc, attr, overload) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate0<> FD; \ MAKE_DELEG_void((), ()); \ virtual void Func() \ { SH_HANDLEFUNC_void((), ()); } \ @@ -1220,12 +1111,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN0_void(ifacetype, ifacefunc, attr, overload) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate0<> handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate0<> handler); #define SH_DECL_HOOK0_vafmt(ifacetype, ifacefunc, attr, overload, rettype) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate1 FD; \ MAKE_DELEG(rettype, (const char *px), (px)); \ virtual rettype Func( const char *fmt, ...) \ { \ @@ -1241,12 +1135,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN0_vafmt(ifacetype, ifacefunc, attr, overload, rettype) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate1 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate1 handler); #define SH_DECL_HOOK0_void_vafmt(ifacetype, ifacefunc, attr, overload) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate1 FD; \ MAKE_DELEG_void((const char *px), (px)); \ virtual void Func(const char *fmt, ...) \ { \ @@ -1262,16 +1159,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN0_void_vafmt(ifacetype, ifacefunc, attr, overload) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate1 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate1 handler); #define SH_DECL_MANUALHOOK0(hookname, vtblidx, vtbloffs, thisptroffs, rettype) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate0 FD; \ MAKE_DELEG(rettype, (), ()); \ virtual rettype Func() \ { SH_HANDLEFUNC((), (), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype > CallEC; \ + typedef SourceHook::ExecutableClass0< ::SourceHook::EmptyClass, ECMFP, rettype > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -1285,11 +1185,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN0(hookname, rettype) \ - SH_DECL_MANUALEXTERN(hookname, rettype) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate0 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate0 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(); \ + SourceHook::ExecutableClass0 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK0_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate1 FD; \ MAKE_DELEG(rettype, (const char *px), (px)); \ virtual rettype Func(const char *fmt, ...) \ { \ @@ -1297,7 +1204,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((const char *, ...), ("%s", buf), (buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, const char * > CallEC; \ + typedef SourceHook::ExecutableClass1< ::SourceHook::EmptyClass, ECMFP, rettype, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -1311,16 +1218,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN0_vafmt(hookname, rettype) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate1 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate1 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(const char *, ...); \ + SourceHook::ExecutableClass1 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK0_void(hookname, vtblidx, vtbloffs, thisptroffs) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate0<> FD; \ MAKE_DELEG_void((), ()); \ virtual void Func() \ { SH_HANDLEFUNC_void((), ()); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass0 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0} }; \ @@ -1329,11 +1243,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN0_void(hookname) \ - SH_DECL_MANUALEXTERN_void(hookname) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate0<> handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate0<> handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(); \ + SourceHook::ExecutableClass0 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK0_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate1 FD; \ MAKE_DELEG_void((const char *px), (px)); \ virtual void Func(const char *fmt, ...) \ { \ @@ -1341,7 +1261,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((const char *, ...), ("%s", buf), (buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, const char * > CallEC; \ + typedef SourceHook::ExecutableClass1< ::SourceHook::EmptyClass, ECMFP, void, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0} }; \ @@ -1350,14 +1270,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN0_void_vafmt(hookname) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate1 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate1 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(const char *, ...); \ + SourceHook::ExecutableClass1 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 1 arguments ********* #define SH_DECL_HOOK1(ifacetype, ifacefunc, attr, overload, rettype, param1) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate1 FD; \ MAKE_DELEG(rettype, (param1 p1), (p1)); \ virtual rettype Func(param1 p1) \ { SH_HANDLEFUNC((param1), (p1), rettype); } \ @@ -1370,12 +1295,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN1(ifacetype, ifacefunc, attr, overload, rettype, param1) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate1 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate1 handler); #define SH_DECL_HOOK1_void(ifacetype, ifacefunc, attr, overload, param1) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate1 FD; \ MAKE_DELEG_void((param1 p1), (p1)); \ virtual void Func(param1 p1) \ { SH_HANDLEFUNC_void((param1), (p1)); } \ @@ -1388,12 +1316,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN1_void(ifacetype, ifacefunc, attr, overload, param1) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate1 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate1 handler); #define SH_DECL_HOOK1_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate2 FD; \ MAKE_DELEG(rettype, (param1 p1, const char *px), (p1, px)); \ virtual rettype Func(param1 p1 , const char *fmt, ...) \ { \ @@ -1409,12 +1340,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN1_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate2 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate2 handler); #define SH_DECL_HOOK1_void_vafmt(ifacetype, ifacefunc, attr, overload, param1) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate2 FD; \ MAKE_DELEG_void((param1 p1, const char *px), (p1, px)); \ virtual void Func(param1 p1, const char *fmt, ...) \ { \ @@ -1430,16 +1364,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN1_void_vafmt(ifacetype, ifacefunc, attr, overload, param1) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate2 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate2 handler); #define SH_DECL_MANUALHOOK1(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate1 FD; \ MAKE_DELEG(rettype, (param1 p1), (p1)); \ virtual rettype Func(param1 p1) \ { SH_HANDLEFUNC((param1), (p1), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1 > CallEC; \ + typedef SourceHook::ExecutableClass1< ::SourceHook::EmptyClass, ECMFP, rettype, param1 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -1453,11 +1390,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN1(hookname, rettype, param1) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate1 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate1 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1); \ + SourceHook::ExecutableClass1 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK1_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate2 FD; \ MAKE_DELEG(rettype, (param1 p1, const char *px), (p1, px)); \ virtual rettype Func(param1 p1, const char *fmt, ...) \ { \ @@ -1465,7 +1409,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, const char *, ...), (p1, "%s", buf), (p1, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, const char * > CallEC; \ + typedef SourceHook::ExecutableClass2< ::SourceHook::EmptyClass, ECMFP, rettype, param1, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -1479,16 +1423,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN1_vafmt(hookname, rettype, param1) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate2 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate2 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, const char *, ...); \ + SourceHook::ExecutableClass2 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK1_void(hookname, vtblidx, vtbloffs, thisptroffs, param1) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate1 FD; \ MAKE_DELEG_void((param1 p1), (p1)); \ virtual void Func(param1 p1) \ { SH_HANDLEFUNC_void((param1), (p1)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass1 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1) }; \ @@ -1497,11 +1448,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN1_void(hookname, param1) \ - SH_DECL_MANUALEXTERN_void(hookname, param1) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate1 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate1 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1); \ + SourceHook::ExecutableClass1 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK1_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate2 FD; \ MAKE_DELEG_void((param1 p1, const char *px), (p1, px)); \ virtual void Func(param1 p1, const char *fmt, ...) \ { \ @@ -1509,7 +1466,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, const char *, ...), (p1, "%s", buf), (p1, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, const char * > CallEC; \ + typedef SourceHook::ExecutableClass2< ::SourceHook::EmptyClass, ECMFP, void, param1, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1) }; \ @@ -1518,14 +1475,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN1_void_vafmt(hookname, param1) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate2 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate2 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, const char *, ...); \ + SourceHook::ExecutableClass2 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 2 arguments ********* #define SH_DECL_HOOK2(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate2 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2), (p1, p2)); \ virtual rettype Func(param1 p1, param2 p2) \ { SH_HANDLEFUNC((param1, param2), (p1, p2), rettype); } \ @@ -1538,12 +1500,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN2(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate2 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate2 handler); #define SH_DECL_HOOK2_void(ifacetype, ifacefunc, attr, overload, param1, param2) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate2 FD; \ MAKE_DELEG_void((param1 p1, param2 p2), (p1, p2)); \ virtual void Func(param1 p1, param2 p2) \ { SH_HANDLEFUNC_void((param1, param2), (p1, p2)); } \ @@ -1556,12 +1521,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN2_void(ifacetype, ifacefunc, attr, overload, param1, param2) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate2 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate2 handler); #define SH_DECL_HOOK2_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate3 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, const char *px), (p1, p2, px)); \ virtual rettype Func(param1 p1, param2 p2 , const char *fmt, ...) \ { \ @@ -1577,12 +1545,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN2_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate3 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate3 handler); #define SH_DECL_HOOK2_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate3 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, const char *px), (p1, p2, px)); \ virtual void Func(param1 p1, param2 p2, const char *fmt, ...) \ { \ @@ -1598,16 +1569,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN2_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate3 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate3 handler); #define SH_DECL_MANUALHOOK2(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate2 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2), (p1, p2)); \ virtual rettype Func(param1 p1, param2 p2) \ { SH_HANDLEFUNC((param1, param2), (p1, p2), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2 > CallEC; \ + typedef SourceHook::ExecutableClass2< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -1621,11 +1595,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN2(hookname, rettype, param1, param2) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate2 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate2 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2); \ + SourceHook::ExecutableClass2 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK2_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate3 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, const char *px), (p1, p2, px)); \ virtual rettype Func(param1 p1, param2 p2, const char *fmt, ...) \ { \ @@ -1633,7 +1614,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, const char *, ...), (p1, p2, "%s", buf), (p1, p2, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, const char * > CallEC; \ + typedef SourceHook::ExecutableClass3< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -1647,16 +1628,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN2_vafmt(hookname, rettype, param1, param2) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate3 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate3 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, const char *, ...); \ + SourceHook::ExecutableClass3 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK2_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate2 FD; \ MAKE_DELEG_void((param1 p1, param2 p2), (p1, p2)); \ virtual void Func(param1 p1, param2 p2) \ { SH_HANDLEFUNC_void((param1, param2), (p1, p2)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass2 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2) }; \ @@ -1665,11 +1653,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN2_void(hookname, param1, param2) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate2 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate2 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2); \ + SourceHook::ExecutableClass2 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK2_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate3 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, const char *px), (p1, p2, px)); \ virtual void Func(param1 p1, param2 p2, const char *fmt, ...) \ { \ @@ -1677,7 +1671,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, const char *, ...), (p1, p2, "%s", buf), (p1, p2, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, const char * > CallEC; \ + typedef SourceHook::ExecutableClass3< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2) }; \ @@ -1686,14 +1680,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN2_void_vafmt(hookname, param1, param2) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate3 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate3 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, const char *, ...); \ + SourceHook::ExecutableClass3 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 3 arguments ********* #define SH_DECL_HOOK3(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate3 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3), (p1, p2, p3)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3) \ { SH_HANDLEFUNC((param1, param2, param3), (p1, p2, p3), rettype); } \ @@ -1706,12 +1705,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN3(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate3 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate3 handler); #define SH_DECL_HOOK3_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate3 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3), (p1, p2, p3)); \ virtual void Func(param1 p1, param2 p2, param3 p3) \ { SH_HANDLEFUNC_void((param1, param2, param3), (p1, p2, p3)); } \ @@ -1724,12 +1726,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN3_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate3 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate3 handler); #define SH_DECL_HOOK3_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate4 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, const char *px), (p1, p2, p3, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3 , const char *fmt, ...) \ { \ @@ -1745,12 +1750,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN3_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate4 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate4 handler); #define SH_DECL_HOOK3_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate4 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, const char *px), (p1, p2, p3, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, const char *fmt, ...) \ { \ @@ -1766,16 +1774,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN3_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate4 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate4 handler); #define SH_DECL_MANUALHOOK3(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate3 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3), (p1, p2, p3)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3) \ { SH_HANDLEFUNC((param1, param2, param3), (p1, p2, p3), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3 > CallEC; \ + typedef SourceHook::ExecutableClass3< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -1789,11 +1800,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN3(hookname, rettype, param1, param2, param3) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate3 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate3 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3); \ + SourceHook::ExecutableClass3 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK3_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate4 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, const char *px), (p1, p2, p3, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, const char *fmt, ...) \ { \ @@ -1801,7 +1819,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, const char *, ...), (p1, p2, p3, "%s", buf), (p1, p2, p3, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, const char * > CallEC; \ + typedef SourceHook::ExecutableClass4< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -1815,16 +1833,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN3_vafmt(hookname, rettype, param1, param2, param3) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate4 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate4 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, const char *, ...); \ + SourceHook::ExecutableClass4 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK3_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate3 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3), (p1, p2, p3)); \ virtual void Func(param1 p1, param2 p2, param3 p3) \ { SH_HANDLEFUNC_void((param1, param2, param3), (p1, p2, p3)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass3 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3) }; \ @@ -1833,11 +1858,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN3_void(hookname, param1, param2, param3) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate3 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate3 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3); \ + SourceHook::ExecutableClass3 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK3_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate4 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, const char *px), (p1, p2, p3, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, const char *fmt, ...) \ { \ @@ -1845,7 +1876,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, const char *, ...), (p1, p2, p3, "%s", buf), (p1, p2, p3, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, const char * > CallEC; \ + typedef SourceHook::ExecutableClass4< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3) }; \ @@ -1854,14 +1885,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN3_void_vafmt(hookname, param1, param2, param3) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate4 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate4 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, const char *, ...); \ + SourceHook::ExecutableClass4 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 4 arguments ********* #define SH_DECL_HOOK4(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate4 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4), (p1, p2, p3, p4)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4) \ { SH_HANDLEFUNC((param1, param2, param3, param4), (p1, p2, p3, p4), rettype); } \ @@ -1874,12 +1910,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN4(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate4 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate4 handler); #define SH_DECL_HOOK4_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate4 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4), (p1, p2, p3, p4)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4), (p1, p2, p3, p4)); } \ @@ -1892,12 +1931,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN4_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate4 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate4 handler); #define SH_DECL_HOOK4_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate5 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, const char *px), (p1, p2, p3, p4, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4 , const char *fmt, ...) \ { \ @@ -1913,12 +1955,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN4_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate5 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate5 handler); #define SH_DECL_HOOK4_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate5 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, const char *px), (p1, p2, p3, p4, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, const char *fmt, ...) \ { \ @@ -1934,16 +1979,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN4_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate5 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate5 handler); #define SH_DECL_MANUALHOOK4(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate4 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4), (p1, p2, p3, p4)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4) \ { SH_HANDLEFUNC((param1, param2, param3, param4), (p1, p2, p3, p4), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4 > CallEC; \ + typedef SourceHook::ExecutableClass4< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -1957,11 +2005,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN4(hookname, rettype, param1, param2, param3, param4) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate4 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate4 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4); \ + SourceHook::ExecutableClass4 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK4_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate5 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, const char *px), (p1, p2, p3, p4, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, const char *fmt, ...) \ { \ @@ -1969,7 +2024,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, const char *, ...), (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, const char * > CallEC; \ + typedef SourceHook::ExecutableClass5< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -1983,16 +2038,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN4_vafmt(hookname, rettype, param1, param2, param3, param4) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate5 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate5 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, const char *, ...); \ + SourceHook::ExecutableClass5 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK4_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate4 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4), (p1, p2, p3, p4)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4), (p1, p2, p3, p4)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass4 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4) }; \ @@ -2001,11 +2063,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN4_void(hookname, param1, param2, param3, param4) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate4 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate4 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4); \ + SourceHook::ExecutableClass4 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK4_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate5 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, const char *px), (p1, p2, p3, p4, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, const char *fmt, ...) \ { \ @@ -2013,7 +2081,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, const char *, ...), (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, const char * > CallEC; \ + typedef SourceHook::ExecutableClass5< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4) }; \ @@ -2022,14 +2090,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN4_void_vafmt(hookname, param1, param2, param3, param4) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate5 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate5 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, const char *, ...); \ + SourceHook::ExecutableClass5 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 5 arguments ********* #define SH_DECL_HOOK5(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate5 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5), (p1, p2, p3, p4, p5)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5), rettype); } \ @@ -2042,12 +2115,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN5(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate5 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate5 handler); #define SH_DECL_HOOK5_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate5 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5), (p1, p2, p3, p4, p5)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5)); } \ @@ -2060,12 +2136,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN5_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate5 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate5 handler); #define SH_DECL_HOOK5_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate6 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *px), (p1, p2, p3, p4, p5, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5 , const char *fmt, ...) \ { \ @@ -2081,12 +2160,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN5_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate6 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate6 handler); #define SH_DECL_HOOK5_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate6 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *px), (p1, p2, p3, p4, p5, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *fmt, ...) \ { \ @@ -2102,16 +2184,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN5_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate6 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate6 handler); #define SH_DECL_MANUALHOOK5(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate5 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5), (p1, p2, p3, p4, p5)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5 > CallEC; \ + typedef SourceHook::ExecutableClass5< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -2125,11 +2210,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN5(hookname, rettype, param1, param2, param3, param4, param5) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate5 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate5 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5); \ + SourceHook::ExecutableClass5 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK5_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate6 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *px), (p1, p2, p3, p4, p5, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *fmt, ...) \ { \ @@ -2137,7 +2229,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, const char *, ...), (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, const char * > CallEC; \ + typedef SourceHook::ExecutableClass6< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -2151,16 +2243,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN5_vafmt(hookname, rettype, param1, param2, param3, param4, param5) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate6 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate6 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, const char *, ...); \ + SourceHook::ExecutableClass6 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK5_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate5 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5), (p1, p2, p3, p4, p5)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass5 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5) }; \ @@ -2169,11 +2268,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN5_void(hookname, param1, param2, param3, param4, param5) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate5 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate5 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5); \ + SourceHook::ExecutableClass5 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK5_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate6 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *px), (p1, p2, p3, p4, p5, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *fmt, ...) \ { \ @@ -2181,7 +2286,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, const char *, ...), (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, const char * > CallEC; \ + typedef SourceHook::ExecutableClass6< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5) }; \ @@ -2190,14 +2295,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN5_void_vafmt(hookname, param1, param2, param3, param4, param5) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate6 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate6 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, const char *, ...); \ + SourceHook::ExecutableClass6 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 6 arguments ********* #define SH_DECL_HOOK6(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate6 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6), (p1, p2, p3, p4, p5, p6)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6), rettype); } \ @@ -2210,12 +2320,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN6(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate6 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate6 handler); #define SH_DECL_HOOK6_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate6 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6), (p1, p2, p3, p4, p5, p6)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6)); } \ @@ -2228,12 +2341,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN6_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate6 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate6 handler); #define SH_DECL_HOOK6_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate7 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *px), (p1, p2, p3, p4, p5, p6, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6 , const char *fmt, ...) \ { \ @@ -2249,12 +2365,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN6_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate7 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate7 handler); #define SH_DECL_HOOK6_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate7 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *px), (p1, p2, p3, p4, p5, p6, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *fmt, ...) \ { \ @@ -2270,16 +2389,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN6_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate7 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate7 handler); #define SH_DECL_MANUALHOOK6(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate6 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6), (p1, p2, p3, p4, p5, p6)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6 > CallEC; \ + typedef SourceHook::ExecutableClass6< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -2293,11 +2415,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN6(hookname, rettype, param1, param2, param3, param4, param5, param6) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate6 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate6 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6); \ + SourceHook::ExecutableClass6 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK6_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate7 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *px), (p1, p2, p3, p4, p5, p6, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *fmt, ...) \ { \ @@ -2305,7 +2434,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, const char *, ...), (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, const char * > CallEC; \ + typedef SourceHook::ExecutableClass7< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -2319,16 +2448,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN6_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate7 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate7 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, const char *, ...); \ + SourceHook::ExecutableClass7 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK6_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate6 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6), (p1, p2, p3, p4, p5, p6)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass6 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6) }; \ @@ -2337,11 +2473,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN6_void(hookname, param1, param2, param3, param4, param5, param6) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate6 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate6 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6); \ + SourceHook::ExecutableClass6 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK6_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate7 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *px), (p1, p2, p3, p4, p5, p6, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *fmt, ...) \ { \ @@ -2349,7 +2491,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, const char *, ...), (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, const char * > CallEC; \ + typedef SourceHook::ExecutableClass7< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6) }; \ @@ -2358,14 +2500,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN6_void_vafmt(hookname, param1, param2, param3, param4, param5, param6) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate7 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate7 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, const char *, ...); \ + SourceHook::ExecutableClass7 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 7 arguments ********* #define SH_DECL_HOOK7(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate7 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7), (p1, p2, p3, p4, p5, p6, p7)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7), rettype); } \ @@ -2378,12 +2525,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN7(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate7 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate7 handler); #define SH_DECL_HOOK7_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate7 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7), (p1, p2, p3, p4, p5, p6, p7)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7)); } \ @@ -2396,12 +2546,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN7_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate7 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate7 handler); #define SH_DECL_HOOK7_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate8 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *px), (p1, p2, p3, p4, p5, p6, p7, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7 , const char *fmt, ...) \ { \ @@ -2417,12 +2570,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN7_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate8 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate8 handler); #define SH_DECL_HOOK7_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate8 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *px), (p1, p2, p3, p4, p5, p6, p7, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *fmt, ...) \ { \ @@ -2438,16 +2594,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN7_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate8 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate8 handler); #define SH_DECL_MANUALHOOK7(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate7 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7), (p1, p2, p3, p4, p5, p6, p7)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7 > CallEC; \ + typedef SourceHook::ExecutableClass7< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -2461,11 +2620,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN7(hookname, rettype, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate7 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate7 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7); \ + SourceHook::ExecutableClass7 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK7_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate8 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *px), (p1, p2, p3, p4, p5, p6, p7, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *fmt, ...) \ { \ @@ -2473,7 +2639,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, const char * > CallEC; \ + typedef SourceHook::ExecutableClass8< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -2487,16 +2653,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN7_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate8 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate8 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, const char *, ...); \ + SourceHook::ExecutableClass8 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK7_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate7 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7), (p1, p2, p3, p4, p5, p6, p7)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass7 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7) }; \ @@ -2505,11 +2678,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN7_void(hookname, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate7 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate7 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7); \ + SourceHook::ExecutableClass7 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK7_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate8 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *px), (p1, p2, p3, p4, p5, p6, p7, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *fmt, ...) \ { \ @@ -2517,7 +2696,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, const char * > CallEC; \ + typedef SourceHook::ExecutableClass8< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7) }; \ @@ -2526,14 +2705,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN7_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate8 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate8 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, const char *, ...); \ + SourceHook::ExecutableClass8 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 8 arguments ********* #define SH_DECL_HOOK8(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate8 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8), (p1, p2, p3, p4, p5, p6, p7, p8)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8), rettype); } \ @@ -2546,12 +2730,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN8(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate8 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate8 handler); #define SH_DECL_HOOK8_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate8 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8), (p1, p2, p3, p4, p5, p6, p7, p8)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8)); } \ @@ -2564,12 +2751,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN8_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate8 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate8 handler); #define SH_DECL_HOOK8_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate9 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8 , const char *fmt, ...) \ { \ @@ -2585,12 +2775,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN8_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate9 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate9 handler); #define SH_DECL_HOOK8_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate9 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *fmt, ...) \ { \ @@ -2606,16 +2799,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN8_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate9 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate9 handler); #define SH_DECL_MANUALHOOK8(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate8 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8), (p1, p2, p3, p4, p5, p6, p7, p8)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8 > CallEC; \ + typedef SourceHook::ExecutableClass8< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -2629,11 +2825,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN8(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate8 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate8 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8); \ + SourceHook::ExecutableClass8 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK8_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate9 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *fmt, ...) \ { \ @@ -2641,7 +2844,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, const char * > CallEC; \ + typedef SourceHook::ExecutableClass9< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -2655,16 +2858,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN8_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate9 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate9 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, const char *, ...); \ + SourceHook::ExecutableClass9 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK8_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate8 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8), (p1, p2, p3, p4, p5, p6, p7, p8)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass8 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8) }; \ @@ -2673,11 +2883,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN8_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate8 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate8 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8); \ + SourceHook::ExecutableClass8 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK8_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate9 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *fmt, ...) \ { \ @@ -2685,7 +2901,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, const char * > CallEC; \ + typedef SourceHook::ExecutableClass9< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8) }; \ @@ -2694,14 +2910,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN8_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate9 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate9 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, const char *, ...); \ + SourceHook::ExecutableClass9 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 9 arguments ********* #define SH_DECL_HOOK9(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate9 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9), rettype); } \ @@ -2714,12 +2935,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN9(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate9 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate9 handler); #define SH_DECL_HOOK9_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate9 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); } \ @@ -2732,12 +2956,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN9_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate9 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate9 handler); #define SH_DECL_HOOK9_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate10 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9 , const char *fmt, ...) \ { \ @@ -2753,12 +2980,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN9_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate10 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate10 handler); #define SH_DECL_HOOK9_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate10 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *fmt, ...) \ { \ @@ -2774,16 +3004,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN9_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate10 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate10 handler); #define SH_DECL_MANUALHOOK9(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate9 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9 > CallEC; \ + typedef SourceHook::ExecutableClass9< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -2797,11 +3030,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN9(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate9 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate9 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9); \ + SourceHook::ExecutableClass9 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK9_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate10 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *fmt, ...) \ { \ @@ -2809,7 +3049,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, const char * > CallEC; \ + typedef SourceHook::ExecutableClass10< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -2823,16 +3063,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN9_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate10 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate10 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, const char *, ...); \ + SourceHook::ExecutableClass10 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK9_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate9 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass9 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9) }; \ @@ -2841,11 +3088,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN9_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate9 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate9 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9); \ + SourceHook::ExecutableClass9 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK9_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate10 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *fmt, ...) \ { \ @@ -2853,7 +3106,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, const char * > CallEC; \ + typedef SourceHook::ExecutableClass10< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9) }; \ @@ -2862,14 +3115,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN9_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate10 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate10 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, const char *, ...); \ + SourceHook::ExecutableClass10 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 10 arguments ********* #define SH_DECL_HOOK10(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate10 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), rettype); } \ @@ -2882,12 +3140,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN10(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate10 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate10 handler); #define SH_DECL_HOOK10_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate10 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); } \ @@ -2900,12 +3161,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN10_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate10 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate10 handler); #define SH_DECL_HOOK10_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate11 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10 , const char *fmt, ...) \ { \ @@ -2921,12 +3185,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN10_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate11 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate11 handler); #define SH_DECL_HOOK10_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate11 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *fmt, ...) \ { \ @@ -2942,16 +3209,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN10_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate11 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate11 handler); #define SH_DECL_MANUALHOOK10(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate10 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10 > CallEC; \ + typedef SourceHook::ExecutableClass10< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -2965,11 +3235,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN10(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate10 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate10 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); \ + SourceHook::ExecutableClass10 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK10_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate11 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *fmt, ...) \ { \ @@ -2977,7 +3254,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char * > CallEC; \ + typedef SourceHook::ExecutableClass11< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -2991,16 +3268,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN10_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate11 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate11 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char *, ...); \ + SourceHook::ExecutableClass11 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK10_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate10 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass10 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10) }; \ @@ -3009,11 +3293,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN10_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate10 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate10 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); \ + SourceHook::ExecutableClass10 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK10_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate11 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *fmt, ...) \ { \ @@ -3021,7 +3311,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char * > CallEC; \ + typedef SourceHook::ExecutableClass11< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10) }; \ @@ -3030,14 +3320,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN10_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate11 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate11 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char *, ...); \ + SourceHook::ExecutableClass11 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 11 arguments ********* #define SH_DECL_HOOK11(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate11 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), rettype); } \ @@ -3050,12 +3345,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN11(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate11 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate11 handler); #define SH_DECL_HOOK11_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate11 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); } \ @@ -3068,12 +3366,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN11_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate11 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate11 handler); #define SH_DECL_HOOK11_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate12 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11 , const char *fmt, ...) \ { \ @@ -3089,12 +3390,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN11_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate12 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate12 handler); #define SH_DECL_HOOK11_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate12 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *fmt, ...) \ { \ @@ -3110,16 +3414,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN11_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate12 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate12 handler); #define SH_DECL_MANUALHOOK11(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate11 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11 > CallEC; \ + typedef SourceHook::ExecutableClass11< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -3133,11 +3440,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN11(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate11 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate11 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); \ + SourceHook::ExecutableClass11 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK11_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate12 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *fmt, ...) \ { \ @@ -3145,7 +3459,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char * > CallEC; \ + typedef SourceHook::ExecutableClass12< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -3159,16 +3473,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN11_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate12 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate12 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char *, ...); \ + SourceHook::ExecutableClass12 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK11_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate11 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass11 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11) }; \ @@ -3177,11 +3498,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN11_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate11 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate11 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); \ + SourceHook::ExecutableClass11 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK11_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate12 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *fmt, ...) \ { \ @@ -3189,7 +3516,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char * > CallEC; \ + typedef SourceHook::ExecutableClass12< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11) }; \ @@ -3198,14 +3525,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN11_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate12 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate12 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char *, ...); \ + SourceHook::ExecutableClass12 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 12 arguments ********* #define SH_DECL_HOOK12(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate12 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), rettype); } \ @@ -3218,12 +3550,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN12(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate12 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate12 handler); #define SH_DECL_HOOK12_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate12 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); } \ @@ -3236,12 +3571,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN12_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate12 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate12 handler); #define SH_DECL_HOOK12_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate13 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12 , const char *fmt, ...) \ { \ @@ -3257,12 +3595,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN12_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate13 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate13 handler); #define SH_DECL_HOOK12_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate13 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *fmt, ...) \ { \ @@ -3278,16 +3619,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN12_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate13 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate13 handler); #define SH_DECL_MANUALHOOK12(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate12 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12 > CallEC; \ + typedef SourceHook::ExecutableClass12< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -3301,11 +3645,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN12(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate12 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate12 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12); \ + SourceHook::ExecutableClass12 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK12_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate13 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *fmt, ...) \ { \ @@ -3313,7 +3664,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char * > CallEC; \ + typedef SourceHook::ExecutableClass13< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -3327,16 +3678,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN12_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate13 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate13 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char *, ...); \ + SourceHook::ExecutableClass13 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK12_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate12 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass12 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12) }; \ @@ -3345,11 +3703,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN12_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate12 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate12 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12); \ + SourceHook::ExecutableClass12 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK12_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate13 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *fmt, ...) \ { \ @@ -3357,7 +3721,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char * > CallEC; \ + typedef SourceHook::ExecutableClass13< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12) }; \ @@ -3366,14 +3730,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN12_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate13 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate13 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char *, ...); \ + SourceHook::ExecutableClass13 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 13 arguments ********* #define SH_DECL_HOOK13(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate13 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), rettype); } \ @@ -3386,12 +3755,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN13(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate13 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate13 handler); #define SH_DECL_HOOK13_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate13 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); } \ @@ -3404,12 +3776,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN13_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate13 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate13 handler); #define SH_DECL_HOOK13_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate14 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13 , const char *fmt, ...) \ { \ @@ -3425,12 +3800,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN13_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate14 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate14 handler); #define SH_DECL_HOOK13_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate14 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *fmt, ...) \ { \ @@ -3446,16 +3824,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN13_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate14 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate14 handler); #define SH_DECL_MANUALHOOK13(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate13 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13 > CallEC; \ + typedef SourceHook::ExecutableClass13< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -3469,11 +3850,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN13(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate13 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate13 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13); \ + SourceHook::ExecutableClass13 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK13_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate14 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *fmt, ...) \ { \ @@ -3481,7 +3869,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char * > CallEC; \ + typedef SourceHook::ExecutableClass14< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -3495,16 +3883,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN13_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate14 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate14 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char *, ...); \ + SourceHook::ExecutableClass14 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK13_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate13 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass13 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13) }; \ @@ -3513,11 +3908,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN13_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate13 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate13 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13); \ + SourceHook::ExecutableClass13 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK13_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate14 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *fmt, ...) \ { \ @@ -3525,7 +3926,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char * > CallEC; \ + typedef SourceHook::ExecutableClass14< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13) }; \ @@ -3534,14 +3935,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN13_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate14 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate14 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char *, ...); \ + SourceHook::ExecutableClass14 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 14 arguments ********* #define SH_DECL_HOOK14(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate14 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), rettype); } \ @@ -3554,12 +3960,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN14(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate14 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate14 handler); #define SH_DECL_HOOK14_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate14 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); } \ @@ -3572,12 +3981,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN14_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate14 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate14 handler); #define SH_DECL_HOOK14_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate15 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14 , const char *fmt, ...) \ { \ @@ -3593,12 +4005,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN14_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate15 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate15 handler); #define SH_DECL_HOOK14_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate15 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *fmt, ...) \ { \ @@ -3614,16 +4029,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN14_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate15 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate15 handler); #define SH_DECL_MANUALHOOK14(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate14 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14 > CallEC; \ + typedef SourceHook::ExecutableClass14< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -3637,11 +4055,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN14(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate14 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate14 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14); \ + SourceHook::ExecutableClass14 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK14_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate15 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *fmt, ...) \ { \ @@ -3649,7 +4074,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char * > CallEC; \ + typedef SourceHook::ExecutableClass15< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -3663,16 +4088,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN14_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate15 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate15 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char *, ...); \ + SourceHook::ExecutableClass15 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK14_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate14 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass14 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14) }; \ @@ -3681,11 +4113,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN14_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate14 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate14 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14); \ + SourceHook::ExecutableClass14 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK14_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate15 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *fmt, ...) \ { \ @@ -3693,7 +4131,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char * > CallEC; \ + typedef SourceHook::ExecutableClass15< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14) }; \ @@ -3702,14 +4140,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN14_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate15 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate15 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char *, ...); \ + SourceHook::ExecutableClass15 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 15 arguments ********* #define SH_DECL_HOOK15(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate15 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), rettype); } \ @@ -3722,12 +4165,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN15(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate15 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate15 handler); #define SH_DECL_HOOK15_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate15 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); } \ @@ -3740,12 +4186,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN15_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate15 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate15 handler); #define SH_DECL_HOOK15_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate16 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15 , const char *fmt, ...) \ { \ @@ -3761,12 +4210,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN15_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate16 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate16 handler); #define SH_DECL_HOOK15_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate16 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *fmt, ...) \ { \ @@ -3782,16 +4234,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN15_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate16 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate16 handler); #define SH_DECL_MANUALHOOK15(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate15 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15 > CallEC; \ + typedef SourceHook::ExecutableClass15< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -3805,11 +4260,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN15(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate15 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate15 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15); \ + SourceHook::ExecutableClass15 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK15_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate16 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *fmt, ...) \ { \ @@ -3817,7 +4279,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char * > CallEC; \ + typedef SourceHook::ExecutableClass16< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -3831,16 +4293,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN15_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate16 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate16 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char *, ...); \ + SourceHook::ExecutableClass16 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK15_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate15 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass15 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15) }; \ @@ -3849,11 +4318,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN15_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate15 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate15 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15); \ + SourceHook::ExecutableClass15 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK15_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate16 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *fmt, ...) \ { \ @@ -3861,7 +4336,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char * > CallEC; \ + typedef SourceHook::ExecutableClass16< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15) }; \ @@ -3870,14 +4345,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN15_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate16 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate16 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char *, ...); \ + SourceHook::ExecutableClass16 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 16 arguments ********* #define SH_DECL_HOOK16(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate16 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), rettype); } \ @@ -3890,12 +4370,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN16(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate16 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate16 handler); #define SH_DECL_HOOK16_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate16 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); } \ @@ -3908,12 +4391,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN16_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate16 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate16 handler); #define SH_DECL_HOOK16_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate17 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16 , const char *fmt, ...) \ { \ @@ -3929,12 +4415,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN16_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate17 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate17 handler); #define SH_DECL_HOOK16_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate17 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *fmt, ...) \ { \ @@ -3950,16 +4439,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN16_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate17 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate17 handler); #define SH_DECL_MANUALHOOK16(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate16 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16 > CallEC; \ + typedef SourceHook::ExecutableClass16< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -3973,11 +4465,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN16(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate16 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate16 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16); \ + SourceHook::ExecutableClass16 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK16_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate17 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *fmt, ...) \ { \ @@ -3985,7 +4484,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char * > CallEC; \ + typedef SourceHook::ExecutableClass17< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -3999,16 +4498,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN16_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate17 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate17 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...); \ + SourceHook::ExecutableClass17 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK16_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate16 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass16 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16) }; \ @@ -4017,11 +4523,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN16_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate16 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate16 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16); \ + SourceHook::ExecutableClass16 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK16_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate17 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *fmt, ...) \ { \ @@ -4029,7 +4541,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char * > CallEC; \ + typedef SourceHook::ExecutableClass17< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16) }; \ @@ -4038,14 +4550,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN16_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate17 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate17 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...); \ + SourceHook::ExecutableClass17 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 17 arguments ********* #define SH_DECL_HOOK17(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate17 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), rettype); } \ @@ -4058,12 +4575,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN17(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate17 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate17 handler); #define SH_DECL_HOOK17_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate17 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); } \ @@ -4076,12 +4596,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN17_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate17 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate17 handler); #define SH_DECL_HOOK17_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate18 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17 , const char *fmt, ...) \ { \ @@ -4097,12 +4620,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN17_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate18 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate18 handler); #define SH_DECL_HOOK17_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate18 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *fmt, ...) \ { \ @@ -4118,16 +4644,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN17_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate18 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate18 handler); #define SH_DECL_MANUALHOOK17(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate17 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17 > CallEC; \ + typedef SourceHook::ExecutableClass17< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -4141,11 +4670,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN17(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate17 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate17 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17); \ + SourceHook::ExecutableClass17 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK17_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate18 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *fmt, ...) \ { \ @@ -4153,7 +4689,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char * > CallEC; \ + typedef SourceHook::ExecutableClass18< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -4167,16 +4703,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN17_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate18 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate18 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...); \ + SourceHook::ExecutableClass18 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK17_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate17 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass17 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17) }; \ @@ -4185,11 +4728,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN17_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate17 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate17 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17); \ + SourceHook::ExecutableClass17 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK17_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate18 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *fmt, ...) \ { \ @@ -4197,7 +4746,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char * > CallEC; \ + typedef SourceHook::ExecutableClass18< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17) }; \ @@ -4206,14 +4755,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN17_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate18 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate18 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...); \ + SourceHook::ExecutableClass18 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 18 arguments ********* #define SH_DECL_HOOK18(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate18 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), rettype); } \ @@ -4226,12 +4780,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN18(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate18 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate18 handler); #define SH_DECL_HOOK18_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate18 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); } \ @@ -4244,12 +4801,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN18_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate18 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate18 handler); #define SH_DECL_HOOK18_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate19 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18 , const char *fmt, ...) \ { \ @@ -4265,12 +4825,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN18_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate19 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate19 handler); #define SH_DECL_HOOK18_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate19 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *fmt, ...) \ { \ @@ -4286,16 +4849,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN18_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate19 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate19 handler); #define SH_DECL_MANUALHOOK18(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate18 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18 > CallEC; \ + typedef SourceHook::ExecutableClass18< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -4309,11 +4875,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN18(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate18 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate18 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18); \ + SourceHook::ExecutableClass18 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK18_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate19 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *fmt, ...) \ { \ @@ -4321,7 +4894,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char * > CallEC; \ + typedef SourceHook::ExecutableClass19< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -4335,16 +4908,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN18_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate19 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate19 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...); \ + SourceHook::ExecutableClass19 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK18_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate18 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass18 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18) }; \ @@ -4353,11 +4933,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN18_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate18 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate18 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18); \ + SourceHook::ExecutableClass18 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK18_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate19 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *fmt, ...) \ { \ @@ -4365,7 +4951,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char * > CallEC; \ + typedef SourceHook::ExecutableClass19< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18) }; \ @@ -4374,14 +4960,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN18_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate19 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate19 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...); \ + SourceHook::ExecutableClass19 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 19 arguments ********* #define SH_DECL_HOOK19(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate19 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), rettype); } \ @@ -4394,12 +4985,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN19(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate19 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate19 handler); #define SH_DECL_HOOK19_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate19 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); } \ @@ -4412,12 +5006,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN19_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate19 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate19 handler); #define SH_DECL_HOOK19_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate20 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19 , const char *fmt, ...) \ { \ @@ -4433,12 +5030,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN19_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate20 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate20 handler); #define SH_DECL_HOOK19_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate20 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \ { \ @@ -4454,16 +5054,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN19_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate20 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate20 handler); #define SH_DECL_MANUALHOOK19(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate19 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19 > CallEC; \ + typedef SourceHook::ExecutableClass19< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -4477,11 +5080,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN19(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate19 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate19 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19); \ + SourceHook::ExecutableClass19 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK19_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate20 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \ { \ @@ -4489,7 +5099,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char * > CallEC; \ + typedef SourceHook::ExecutableClass20< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -4503,16 +5113,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN19_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate20 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate20 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...); \ + SourceHook::ExecutableClass20 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK19_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate19 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass19 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19) }; \ @@ -4521,11 +5138,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN19_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate19 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate19 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19); \ + SourceHook::ExecutableClass19 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK19_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate20 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \ { \ @@ -4533,7 +5156,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char * > CallEC; \ + typedef SourceHook::ExecutableClass20< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19) }; \ @@ -4542,14 +5165,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN19_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate20 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate20 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...); \ + SourceHook::ExecutableClass20 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); // ********* Support for 20 arguments ********* #define SH_DECL_HOOK20(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate20 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), rettype); } \ @@ -4562,12 +5190,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN20(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate20 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate20 handler); #define SH_DECL_HOOK20_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate20 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); } \ @@ -4580,12 +5211,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN20_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate20 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate20 handler); #define SH_DECL_HOOK20_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate21 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20 , const char *fmt, ...) \ { \ @@ -4601,12 +5235,15 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN20_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate21 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate21 handler); #define SH_DECL_HOOK20_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate21 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \ { \ @@ -4622,16 +5259,19 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; #define SH_DECL_EXTERN20_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) + int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate21 handler); \ + bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ + fastdelegate::FastDelegate21 handler); #define SH_DECL_MANUALHOOK20(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate20 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), rettype); } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20 > CallEC; \ + typedef SourceHook::ExecutableClass20< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20 > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -4645,11 +5285,18 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN20(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate20 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate20 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20); \ + SourceHook::ExecutableClass20 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK20_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate21 FD; \ MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, px)); \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \ { \ @@ -4657,7 +5304,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, buf), rettype); \ } \ typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char * > CallEC; \ + typedef SourceHook::ExecutableClass21< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char * > CallEC; \ typedef rettype RetType; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ @@ -4671,16 +5318,23 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) } #define SH_DECL_MANUALEXTERN20_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate21 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate21 handler); \ + rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...); \ + SourceHook::ExecutableClass21 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK20_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate20 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20); \ - typedef SourceHook::ExecutableClassN CallEC; \ + typedef SourceHook::ExecutableClass20 CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19), __SH_GPI(param20) }; \ @@ -4689,11 +5343,17 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN20_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate20 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate20 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20); \ + SourceHook::ExecutableClass20 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); #define SH_DECL_MANUALHOOK20_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ + typedef fastdelegate::FastDelegate21 FD; \ MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, px)); \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \ { \ @@ -4701,7 +5361,7 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, buf)); \ } \ typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char * > CallEC; \ + typedef SourceHook::ExecutableClass21< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char * > CallEC; \ SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ \ const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19), __SH_GPI(param20) }; \ @@ -4710,216 +5370,3499 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; #define SH_DECL_MANUALEXTERN20_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) - + int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ + fastdelegate::FastDelegate21 handler); \ + bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ + fastdelegate::FastDelegate21 handler); \ + void(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...); \ + SourceHook::ExecutableClass21 __SoureceHook_FHM_SHCall##hookname(void *ptr); \ + void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); ////////////////////////////////////////////////////////////////////////// // SH_CALL +#define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \ +{ \ + using namespace ::SourceHook; \ + \ + m_pSH->SetIgnoreHooks(m_VfnPtr); \ + RetType tmpret = (m_ThisPtr->*m_MFP)call; \ + m_pSH->ResetIgnoreHooks(m_VfnPtr); \ + return tmpret; \ +} + +#define SH_MAKE_EXECUTABLECLASS_OB_void(call, prms) \ +{ \ + using namespace ::SourceHook; \ + \ + m_pSH->SetIgnoreHooks(m_VfnPtr); \ + (m_ThisPtr->*m_MFP)call; \ + m_pSH->ResetIgnoreHooks(m_VfnPtr); \ +} + namespace SourceHook { - template - class ExecutableClassN + + // Support for 0 arguments + template class ExecutableClass0 { ObjType *m_ThisPtr; void *m_VfnPtr; MFPType m_MFP; ISourceHook *m_pSH; public: - ExecutableClassN(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) - : m_ThisPtr(tp), - m_VfnPtr(vp), - m_MFP(mfp), - m_pSH(pSH) - { } - - RetType operator()(Params... params) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - RetType tmpret = (m_ThisPtr->*m_MFP)(params...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - return tmpret; - } - - template - RetType operator()(Params... params, MoreParams... more) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - RetType tmpret = (m_ThisPtr->*m_MFP)(params..., more...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - return tmpret; - } + ExecutableClass0(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()() const + SH_MAKE_EXECUTABLECLASS_OB((), ()) + + + template RetType operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB((p1), (Param1)) + + template RetType operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2), (Param1, Param2)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3), (Param1, Param2, Param3)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + }; - template - class ExecutableClassN + template class ExecutableClass0 { ObjType *m_ThisPtr; void *m_VfnPtr; MFPType m_MFP; ISourceHook *m_pSH; public: - ExecutableClassN(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) - : m_ThisPtr(tp), - m_VfnPtr(vp), - m_MFP(mfp), - m_pSH(pSH) - { } - - void operator()(Params... params) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - (m_ThisPtr->*m_MFP)(params...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - } - - template - void operator()(Params... params, MoreParams... more) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - (m_ThisPtr->*m_MFP)(params..., more...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); + ExecutableClass0(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()() const + SH_MAKE_EXECUTABLECLASS_OB_void((), ()) + + + template void operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1), (Param1)) + + template void operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2), (Param1, Param2)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3), (Param1, Param2, Param3)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 1 arguments + template class ExecutableClass1 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass1(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB((p1), (Param1)) + + + template RetType operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2), (Param1, Param2)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3), (Param1, Param2, Param3)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass1 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass1(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1), (Param1)) + + + template void operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2), (Param1, Param2)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3), (Param1, Param2, Param3)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 2 arguments + template class ExecutableClass2 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass2(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2), (Param1, Param2)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3), (Param1, Param2, Param3)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass2 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass2(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2), (Param1, Param2)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3), (Param1, Param2, Param3)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 3 arguments + template class ExecutableClass3 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass3(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3), (Param1, Param2, Param3)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass3 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass3(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3), (Param1, Param2, Param3)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 4 arguments + template class ExecutableClass4 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass4(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass4 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass4(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4), (Param1, Param2, Param3, Param4)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 5 arguments + template class ExecutableClass5 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass5(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass5 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass5(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5), (Param1, Param2, Param3, Param4, Param5)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 6 arguments + template class ExecutableClass6 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass6(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass6 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass6(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6), (Param1, Param2, Param3, Param4, Param5, Param6)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 7 arguments + template class ExecutableClass7 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass7(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass7 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass7(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7), (Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 8 arguments + template class ExecutableClass8 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass8(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass8 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass8(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 9 arguments + template class ExecutableClass9 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass9(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass9 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass9(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 10 arguments + template class ExecutableClass10 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass10(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass10 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass10(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 11 arguments + template class ExecutableClass11 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass11(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass11 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass11(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 12 arguments + template class ExecutableClass12 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass12(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass12 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass12(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 13 arguments + template class ExecutableClass13 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass13(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass13 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass13(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 14 arguments + template class ExecutableClass14 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass14(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass14 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass14(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 15 arguments + template class ExecutableClass15 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass15(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass15 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass15(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 16 arguments + template class ExecutableClass16 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass16(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass16 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass16(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 17 arguments + template class ExecutableClass17 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass17(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass17 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass17(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 18 arguments + template class ExecutableClass18 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass18(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass18 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass18(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 19 arguments + template class ExecutableClass19 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass19(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + template class ExecutableClass19 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass19(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + + + template void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + }; + + // Support for 20 arguments + template class ExecutableClass20 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass20(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + + }; + + template class ExecutableClass20 + { + ObjType *m_ThisPtr; + void *m_VfnPtr; + MFPType m_MFP; + ISourceHook *m_pSH; + public: + ExecutableClass20(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) : m_ThisPtr(tp), + m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH) { } + + void operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const + SH_MAKE_EXECUTABLECLASS_OB_void((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) + + + }; + + +} + +#define SH__CALL_GET_VFNPTR_NORMAL \ + using namespace ::SourceHook; \ + MemFuncInfo mfi = {true, -1, 0, 0}; \ + GetFuncInfo(ptr, mfp, mfi); \ + void *vfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(ptr) + mfi.thisptroffs + mfi.vtbloffs) + mfi.vtblindex); + +#define SH__CALL_GET_VFNPTR_MANUAL \ + using namespace ::SourceHook; \ + void *vfnptr = reinterpret_cast( \ + *reinterpret_cast( (reinterpret_cast(ptr) + thisptroffs + vtbloffs) ) + vtblidx); \ + /* patch mfp */ \ + *reinterpret_cast(&mfp) = *reinterpret_cast(vfnptr); + +// SH_CALL needs to deduce the return type -> it uses templates and function overloading +// That's why SH_CALL takes two parameters: "mfp2" of type RetType(X::*mfp)(params), and "mfp" of type MFP +// The only purpose of the mfp2 parameter is to extract the return type + + +// Support for 0 arguments +template +SourceHook::ExecutableClass0 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass0(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass0 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)()const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass0(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass0 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass0( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 1 arguments +template +SourceHook::ExecutableClass1 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass1(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass1 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass1(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass1 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass1( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 2 arguments +template +SourceHook::ExecutableClass2 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass2(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass2 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass2(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass2 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass2( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 3 arguments +template +SourceHook::ExecutableClass3 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass3(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass3 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass3(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass3 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass3( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 4 arguments +template +SourceHook::ExecutableClass4 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass4(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass4 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass4(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass4 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass4( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 5 arguments +template +SourceHook::ExecutableClass5 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass5(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass5 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass5(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass5 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass5( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 6 arguments +template +SourceHook::ExecutableClass6 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass6(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass6 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass6(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass6 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass6( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 7 arguments +template +SourceHook::ExecutableClass7 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass7(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass7 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass7(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass7 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass7( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 8 arguments +template +SourceHook::ExecutableClass8 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass8(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass8 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass8(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass8 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass8( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 9 arguments +template +SourceHook::ExecutableClass9 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass9(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass9 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass9(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass9 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass9( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 10 arguments +template +SourceHook::ExecutableClass10 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass10(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass10 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass10(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass10 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass10( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 11 arguments +template +SourceHook::ExecutableClass11 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass11(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass11 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass11(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass11 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass11( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 12 arguments +template +SourceHook::ExecutableClass12 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass12(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass12 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass12(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass12 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass12( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 13 arguments +template +SourceHook::ExecutableClass13 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass13(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass13 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass13(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass13 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass13( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 14 arguments +template +SourceHook::ExecutableClass14 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass14(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass14 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass14(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass14 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass14( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 15 arguments +template +SourceHook::ExecutableClass15 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass15(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass15 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass15(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass15 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass15( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 16 arguments +template +SourceHook::ExecutableClass16 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass16(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass16 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass16(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass16 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass16( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 17 arguments +template +SourceHook::ExecutableClass17 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass17(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass17 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass17(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass17 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass17( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 18 arguments +template +SourceHook::ExecutableClass18 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass18(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass18 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass18(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass18 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass18( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 19 arguments +template +SourceHook::ExecutableClass19 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass19(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass19 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass19(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass19 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass19( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + +// Support for 20 arguments +template +SourceHook::ExecutableClass20 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass20(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass20 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass20(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass20 +SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_MANUAL + return SourceHook::ExecutableClass20( + reinterpret_cast(ptr), mfp, vfnptr, shptr); +} + + +#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300 +// GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it + + +// Support for 0 arguments +template +SourceHook::ExecutableClass0 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass0(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass0 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass0(ptr, mfp, vfnptr, shptr); +} + + +// Support for 1 arguments +template +SourceHook::ExecutableClass1 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass1(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass1 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass1(ptr, mfp, vfnptr, shptr); +} + + +// Support for 2 arguments +template +SourceHook::ExecutableClass2 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass2(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass2 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass2(ptr, mfp, vfnptr, shptr); +} + + +// Support for 3 arguments +template +SourceHook::ExecutableClass3 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass3(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass3 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass3(ptr, mfp, vfnptr, shptr); +} + + +// Support for 4 arguments +template +SourceHook::ExecutableClass4 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass4(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass4 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass4(ptr, mfp, vfnptr, shptr); +} + + +// Support for 5 arguments +template +SourceHook::ExecutableClass5 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass5(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass5 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass5(ptr, mfp, vfnptr, shptr); +} + + +// Support for 6 arguments +template +SourceHook::ExecutableClass6 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass6(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass6 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass6(ptr, mfp, vfnptr, shptr); +} + + +// Support for 7 arguments +template +SourceHook::ExecutableClass7 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass7(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass7 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass7(ptr, mfp, vfnptr, shptr); +} + + +// Support for 8 arguments +template +SourceHook::ExecutableClass8 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass8(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass8 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass8(ptr, mfp, vfnptr, shptr); +} + + +// Support for 9 arguments +template +SourceHook::ExecutableClass9 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass9(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass9 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass9(ptr, mfp, vfnptr, shptr); +} + + +// Support for 10 arguments +template +SourceHook::ExecutableClass10 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass10(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass10 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass10(ptr, mfp, vfnptr, shptr); +} + + +// Support for 11 arguments +template +SourceHook::ExecutableClass11 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass11(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass11 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass11(ptr, mfp, vfnptr, shptr); +} + + +// Support for 12 arguments +template +SourceHook::ExecutableClass12 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass12(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass12 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass12(ptr, mfp, vfnptr, shptr); +} + + +// Support for 13 arguments +template +SourceHook::ExecutableClass13 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass13(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass13 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass13(ptr, mfp, vfnptr, shptr); +} + + +// Support for 14 arguments +template +SourceHook::ExecutableClass14 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass14(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass14 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass14(ptr, mfp, vfnptr, shptr); +} + + +// Support for 15 arguments +template +SourceHook::ExecutableClass15 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass15(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass15 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass15(ptr, mfp, vfnptr, shptr); +} + + +// Support for 16 arguments +template +SourceHook::ExecutableClass16 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass16(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass16 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass16(ptr, mfp, vfnptr, shptr); +} + + +// Support for 17 arguments +template +SourceHook::ExecutableClass17 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass17(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass17 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass17(ptr, mfp, vfnptr, shptr); +} + + +// Support for 18 arguments +template +SourceHook::ExecutableClass18 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass18(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass18 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass18(ptr, mfp, vfnptr, shptr); +} + + +// Support for 19 arguments +template +SourceHook::ExecutableClass19 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass19(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass19 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass19(ptr, mfp, vfnptr, shptr); +} + + +// Support for 20 arguments +template +SourceHook::ExecutableClass20 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...), SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass20(ptr, mfp, vfnptr, shptr); +} + +template +SourceHook::ExecutableClass20 +SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...)const, SourceHook::ISourceHook *shptr) +{ + SH__CALL_GET_VFNPTR_NORMAL + return SourceHook::ExecutableClass20(ptr, mfp, vfnptr, shptr); +} + + + +#endif + +#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp), SH_GLOB_SHPTR) +#define SH_MCALL2(ptr, mfp, vtblidx, vtbloffs, thisptroffs) SH_MCALL3((ptr), (mfp), (mfp), (vtblidx), (vtbloffs), (thisptroffs), SH_GLOB_SHPTR) +#define SH_MCALL(ptr, mhookname) __SoureceHook_FHM_SHCall##mhookname(ptr) + +#undef SH_MAKE_EXECUTABLECLASS_OB +#undef SH_MAKE_EXECUTABLECLASS_OB_void + +////////////////////////////////////////////////////////////////////////// +// SetOverrideRet and RecallGetIface for recalls +// These take a ISourceHook pointer instead of using SH_GLOB_SHPTR directly +// The reason is that the user may want to redefine SH_GLOB_SHPTR - then the macros +// (META_RETURN_VALUE_NEWPARAMS) should obey the new pointer. + +namespace SourceHook +{ + // SetOverrideResult used to be implemented like this: + // SetOverrideResult(shptr, memfuncptr, return); + // normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference + // (it thought it was ambigous - the ref and non-ref type) + // so now SetOverrideResult(memfuncptr) deduces the ret type, and returns a functor which does the work + // new syntax: SetOverrideResult(memfuncptr)(shptr, return) + // This also allows us to create a special version for references which respects ReferenceCarrier. + + template struct OverrideFunctor + { + void operator()(ISourceHook *shptr, T res) + { + *reinterpret_cast(shptr->GetOverrideRetPtr()) = res; } }; -} + template struct OverrideFunctor + { + void operator()(ISourceHook *shptr, T &res) + { + // overrideretptr points to ReferenceCarrier + *reinterpret_cast::type *>(shptr->GetOverrideRetPtr()) = res; + } + }; + + // For manual hooks: + // The rettype is passed in manually + template + OverrideFunctor SetOverrideResult() + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)()) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)()) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + { + return OverrideFunctor(); + } -#define SH__CALL_GET_VFNPTR_NORMAL \ - using namespace ::SourceHook; \ - MemFuncInfo mfi = {true, -1, 0, 0}; \ - GetFuncInfo(ptr, mfp, mfi); \ - void *vfnptr = reinterpret_cast( \ - *reinterpret_cast(reinterpret_cast(ptr) + mfi.thisptroffs + mfi.vtbloffs) + mfi.vtblindex); + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...)) + { + return OverrideFunctor(); + } -#define SH__CALL_GET_VFNPTR_MANUAL \ - using namespace ::SourceHook; \ - void *vfnptr = reinterpret_cast( \ - *reinterpret_cast( (reinterpret_cast(ptr) + thisptroffs + vtbloffs) ) + vtblidx); \ - /* patch mfp */ \ - *reinterpret_cast(&mfp) = *reinterpret_cast(vfnptr); + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } -// SH_CALL needs to deduce the return type -> it uses templates and function overloading -// That's why SH_CALL takes two parameters: "mfp2" of type RetType(X::*mfp)(params), and "mfp" of type MFP -// The only purpose of the mfp2 parameter is to extract the return type + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params...), SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); -} + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + { + return OverrideFunctor(); + } -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params..., ...), SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); -} + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...)) + { + return OverrideFunctor(); + } -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params...)const, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); -} + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params..., ...)const, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); -} + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } -template -SourceHook::ExecutableClassN -SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params...), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_MANUAL - return SourceHook::ExecutableClassN( - reinterpret_cast(ptr), mfp, vfnptr, shptr); -} + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + { + return OverrideFunctor(); + } -template -SourceHook::ExecutableClassN -SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params..., ...), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_MANUAL - return SourceHook::ExecutableClassN( - reinterpret_cast(ptr), mfp, vfnptr, shptr); -} + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...)) + { + return OverrideFunctor(); + } -#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp), SH_GLOB_SHPTR) -#define SH_MCALL2(ptr, mfp, vtblidx, vtbloffs, thisptroffs) SH_MCALL3((ptr), (mfp), (mfp), (vtblidx), (vtbloffs), (thisptroffs), SH_GLOB_SHPTR) -#define SH_MCALL(ptr, mhookname) __SoureceHook_FHM_SHCall##mhookname(ptr) + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } -////////////////////////////////////////////////////////////////////////// -// SetOverrideRet and RecallGetIface for recalls -// These take a ISourceHook pointer instead of using SH_GLOB_SHPTR directly -// The reason is that the user may want to redefine SH_GLOB_SHPTR - then the macros -// (META_RETURN_VALUE_NEWPARAMS) should obey the new pointer. + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } -namespace SourceHook -{ - // SetOverrideResult used to be implemented like this: - // SetOverrideResult(shptr, memfuncptr, return); - // normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference - // (it thought it was ambigous - the ref and non-ref type) - // so now SetOverrideResult(memfuncptr) deduces the ret type, and returns a functor which does the work - // new syntax: SetOverrideResult(memfuncptr)(shptr, return) - // This also allows us to create a special version for references which respects ReferenceCarrier. + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) + { + return OverrideFunctor(); + } - template struct OverrideFunctor + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...)) { - void operator()(ISourceHook *shptr, T res) - { - *reinterpret_cast(shptr->GetOverrideRetPtr()) = res; - } - }; - template struct OverrideFunctor + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) { - void operator()(ISourceHook *shptr, T &res) - { - // overrideretptr points to ReferenceCarrier - *reinterpret_cast::type *>(shptr->GetOverrideRetPtr()) = res; - } - }; + return reinterpret_cast(shptr->GetIfacePtr()); + } - // For manual hooks: - // The rettype is passed in manually - template - OverrideFunctor SetOverrideResult() + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...)) + { + return OverrideFunctor(); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + { + return OverrideFunctor(); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...)) { return OverrideFunctor(); } - template - OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Params...)) + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...)) + { + return reinterpret_cast(shptr->GetIfacePtr()); + } + + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) { return OverrideFunctor(); } - template - OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Params..., ...)) + template + OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...)) { return OverrideFunctor(); } - template - Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Params...)) + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)) { return reinterpret_cast(shptr->GetIfacePtr()); } - template - Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Params..., ...)) + template + Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...)) { return reinterpret_cast(shptr->GetIfacePtr()); } + } #endif diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl_cvfnptr.cpp b/utils/mmsource/core/sourcehook/sourcehook_impl_cvfnptr.cpp index 82cdd5cd..3125a163 100644 --- a/utils/mmsource/core/sourcehook/sourcehook_impl_cvfnptr.cpp +++ b/utils/mmsource/core/sourcehook/sourcehook_impl_cvfnptr.cpp @@ -48,35 +48,25 @@ namespace SourceHook #if SH_COMP==SH_COMP_GCC if ((((ptrdiff_t)m_OrigEntry) & 1) != 0) { + // Odd orig entry. + if (SH_PTRSIZE != 4) + { + // We only have code for IA32 atm! + return false; + } + // Generate a new thunk - m_OrigCallThunk = ms_AlignedPageAllocator.Alloc(12); + m_OrigCallThunk = ms_AlignedPageAllocator.Alloc(5); ms_AlignedPageAllocator.SetRW(m_OrigCallThunk); unsigned char* thunkBase = reinterpret_cast(m_OrigCallThunk); - ptrdiff_t offset = reinterpret_cast(m_OrigEntry) - thunkBase - 5; - - if (offset >= INT_MIN && offset <= INT_MAX) - { - *(thunkBase + 0) = 0xE9; // offset jump, immediate operand - ptrdiff_t *offsetAddr = reinterpret_cast(thunkBase + 1); + *(thunkBase + 0) = 0xE9; // offset jump, immediate operand + ptrdiff_t *offsetAddr = reinterpret_cast(thunkBase + 1); - // destination = src + offset + 5 - // <=> offset = destination - src - 5 - *offsetAddr = offset; - } - else - { - // mov rax, m_origEntry - *(thunkBase + 0) = 0x48; - *(thunkBase + 1) = 0xB8; - void **offsetAddr = reinterpret_cast(thunkBase + 2); - - *offsetAddr = m_OrigEntry; - - // jmp rax - *(thunkBase + 10) = 0xFF; - *(thunkBase + 11) = 0xE0; - } + // destination = src + offset + 5 + // <=> offset = destination - src - 5 + *offsetAddr = + (reinterpret_cast(m_OrigEntry) - thunkBase) - 5; ms_AlignedPageAllocator.SetRE(m_OrigCallThunk); } diff --git a/utils/mmsource/core/sourcehook/test/main.cpp b/utils/mmsource/core/sourcehook/test/main.cpp index a04f39c2..dc1fb887 100644 --- a/utils/mmsource/core/sourcehook/test/main.cpp +++ b/utils/mmsource/core/sourcehook/test/main.cpp @@ -18,11 +18,6 @@ using namespace std; bool g_Verbose; -struct Unloader : public SourceHook::Impl::UnloadListener -{ - void ReadyToUnload(SourceHook::Plugin) { } -} g_UnloadListener; - #define DECL_TEST(x) bool Test##x(std::string &error); #define DO_TEST(x) \ @@ -78,17 +73,16 @@ int main(int argc, char *argv[]) DO_TEST(RefRet); DO_TEST(VPHooks); DO_TEST(CPageAlloc); -#if !defined( _M_AMD64 ) && !defined( __amd64__ ) && !defined(__x86_64__) // TODO: Fix for 64-bit DO_TEST(HookManGen); -#endif DO_TEST(OddThunks); cout << endl << "----" << endl << "Passed: " << passed << endl << "Failed: " << failed << endl; cout << "Total: " << passed + failed << endl; - if (failed) - return 1; - return 0; + cout << "Press enter to continue" << endl; + + char x; + cin.read(&x, 1); } SourceHook::ISourceHook *Test_Factory() @@ -106,16 +100,9 @@ void Test_CompleteShutdown(SourceHook::ISourceHook *shptr) static_cast(shptr)->CompleteShutdown(); } -class Listener : public SourceHook::Impl::UnloadListener -{ -public: - void ReadyToUnload(SourceHook::Plugin plug) override { - } -} sListener; - void Test_UnloadPlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) { - static_cast(shptr)->UnloadPlugin(plug, &sListener); + static_cast(shptr)->UnloadPlugin(plug); } void Test_PausePlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) @@ -128,7 +115,6 @@ void Test_UnpausePlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) static_cast(shptr)->UnpausePlugin(plug); } -#if !defined( _M_AMD64 ) && !defined( __amd64__ ) && !defined(__x86_64__) SourceHook::IHookManagerAutoGen *Test_HMAG_Factory(SourceHook::ISourceHook *shptr) { return new SourceHook::Impl::CHookManagerAutoGen(shptr); @@ -138,5 +124,4 @@ void Test_HMAG_Delete(SourceHook::IHookManagerAutoGen *ptr) { delete static_cast(ptr); } -#endif diff --git a/utils/mmsource/core/sourcehook/test/testhookmangen.cpp b/utils/mmsource/core/sourcehook/test/testhookmangen.cpp index 9c0307e4..95e81322 100644 --- a/utils/mmsource/core/sourcehook/test/testhookmangen.cpp +++ b/utils/mmsource/core/sourcehook/test/testhookmangen.cpp @@ -1,5 +1,4 @@ #include -#include #include "sourcehook.h" #include "sourcehook_test.h" #include "testevents.h" @@ -327,8 +326,8 @@ namespace THGM_MAKE_TEST2_void(11, Object<3>, Object<600>&); THGM_SETUP_PI2(11, - Object<3>, SourceHook::PassInfo::PassType_Object, (SourceHook::PassInfo::PassFlag_ByVal | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | SourceHook::PassInfo::PassFlag_CCtor), - Object<600> &, SourceHook::PassInfo::PassType_Object, (SourceHook::PassInfo::PassFlag_ByRef | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | SourceHook::PassInfo::PassFlag_CCtor) + Object<3>, SourceHook::PassInfo::PassType_Object, SourceHook::PassInfo::PassFlag_ByVal | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | SourceHook::PassInfo::PassFlag_CCtor, + Object<600> &, SourceHook::PassInfo::PassType_Object, SourceHook::PassInfo::PassFlag_ByRef | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | SourceHook::PassInfo::PassFlag_CCtor ); THGM_MAKE_TEST0(101, char); @@ -386,8 +385,8 @@ namespace int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal ); THGM_SETUP_RI(110, ObjRet13, SourceHook::PassInfo::PassType_Object, - (SourceHook::PassInfo::PassFlag_ByVal | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | - SourceHook::PassInfo::PassFlag_CCtor | SourceHook::PassInfo::PassFlag_AssignOp)); + SourceHook::PassInfo::PassFlag_ByVal | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | + SourceHook::PassInfo::PassFlag_CCtor | SourceHook::PassInfo::PassFlag_AssignOp); MAKE_OBJRET(111); ObjRet111 g_O111_0; @@ -420,8 +419,8 @@ namespace THGM_MAKE_TEST0(111, ObjRet111& ); THGM_SETUP_PI0(111); THGM_SETUP_RI(111, ObjRet111& , SourceHook::PassInfo::PassType_Object, - (SourceHook::PassInfo::PassFlag_ByRef | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | - SourceHook::PassInfo::PassFlag_CCtor | SourceHook::PassInfo::PassFlag_AssignOp)); + SourceHook::PassInfo::PassFlag_ByRef | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | + SourceHook::PassInfo::PassFlag_CCtor | SourceHook::PassInfo::PassFlag_AssignOp); THGM_MAKE_TEST3_void(150, int, double, int); @@ -481,8 +480,8 @@ namespace THGM_MAKE_TEST1_vafmt_void(214, Object<133>); THGM_SETUP_PI1(214, Object<133>, SourceHook::PassInfo::PassType_Object, - (SourceHook::PassInfo::PassFlag_ByVal | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | - SourceHook::PassInfo::PassFlag_CCtor | SourceHook::PassInfo::PassFlag_AssignOp)); + SourceHook::PassInfo::PassFlag_ByVal | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | + SourceHook::PassInfo::PassFlag_CCtor | SourceHook::PassInfo::PassFlag_AssignOp); MAKE_STATE(State_Hello_Func4_Called); @@ -1094,7 +1093,7 @@ namespace } } -#if !defined( _M_AMD64 ) && !defined( __amd64__ ) && !defined(__x86_64__) + bool TestHookManGen(std::string &error) { GET_SHPTR(g_SHPtr); @@ -1134,7 +1133,6 @@ bool TestHookManGen(std::string &error) return true; } -#endif bool TestCPageAlloc(std::string &error) { @@ -1181,13 +1179,13 @@ bool TestCPageAlloc(std::string &error) test4[i] = (char*) alloc.AllocIsolated(ps / 4); // -> The difference is at least one page - CHECK_COND(static_cast(std::abs(test4[1] - test4[0])) >= ps, "Part 3.1"); - CHECK_COND(static_cast(std::abs(test4[2] - test4[1])) >= ps, "Part 3.2"); - CHECK_COND(static_cast(std::abs(test4[3] - test4[2])) >= ps, "Part 3.3"); + CHECK_COND(static_cast(abs(test4[1] - test4[0])) >= ps, "Part 3.1"); + CHECK_COND(static_cast(abs(test4[2] - test4[1])) >= ps, "Part 3.2"); + CHECK_COND(static_cast(abs(test4[3] - test4[2])) >= ps, "Part 3.3"); - CHECK_COND(static_cast(std::abs(test4[5] - test4[4])) >= ps, "Part 3.4"); - CHECK_COND(static_cast(std::abs(test4[6] - test4[5])) >= ps, "Part 3.5"); - CHECK_COND(static_cast(std::abs(test4[7] - test4[6])) >= ps, "Part 3.6"); + CHECK_COND(static_cast(abs(test4[5] - test4[4])) >= ps, "Part 3.4"); + CHECK_COND(static_cast(abs(test4[6] - test4[5])) >= ps, "Part 3.5"); + CHECK_COND(static_cast(abs(test4[7] - test4[6])) >= ps, "Part 3.6"); // Thus i can set everything except for test4[2] to RE and still write to test4[2] diff --git a/utils/mmsource/core/sourcehook/test/testoddthunks.cpp b/utils/mmsource/core/sourcehook/test/testoddthunks.cpp index 7d625834..6404dedd 100644 --- a/utils/mmsource/core/sourcehook/test/testoddthunks.cpp +++ b/utils/mmsource/core/sourcehook/test/testoddthunks.cpp @@ -1,6 +1,4 @@ #include -#include -#include #include "sourcehook_test.h" #include "sh_pagealloc.h" #include "testevents.h" @@ -98,30 +96,13 @@ namespace // Now generate the jump code g_ThunkAllocator.SetRW(g_OddThunkMemory); + *(base + 0) = 0xE9; // offset jump, immediate operand + ptrdiff_t *offsetAddr = reinterpret_cast(base + 1); + // destination = src + offset + 5 // <=> offset = destination - src - 5 - ptrdiff_t offset = reinterpret_cast(origEntry) - base - 5; - - if (offset >= INT_MIN && offset <= INT_MAX) - { - *(base + 0) = 0xE9; // offset jump, immediate operand - ptrdiff_t *offsetAddr = reinterpret_cast(base + 1); - - *offsetAddr = offset; - } - else - { - // mov rax, origEntry - *(base + 0) = 0x48; - *(base + 1) = 0xB8; - void **offsetAddr = reinterpret_cast(reinterpret_cast(base) + 2); - - *offsetAddr = origEntry; - - // jmp rax - *(base + 10) = 0xFF; - *(base + 11) = 0xE0; - } + *offsetAddr = + (reinterpret_cast(origEntry) - base) - 5; g_ThunkAllocator.SetRE(g_OddThunkMemory); diff --git a/utils/mmsource/core/sourcehook/test/testvphooks.cpp b/utils/mmsource/core/sourcehook/test/testvphooks.cpp index 3aaf51fe..acbeff8b 100644 --- a/utils/mmsource/core/sourcehook/test/testvphooks.cpp +++ b/utils/mmsource/core/sourcehook/test/testvphooks.cpp @@ -109,19 +109,6 @@ namespace SH_DECL_MANUALHOOK1_void(IBase_Func3_Manual, 2, 0, 0, int); } -// Clang is smart enough to see: -// CDerived1 a; -// IBase *p = &a; -// p->Func1() -// -// May bypass the vtable, since p_d1i2 has exactly one assignment. We try to -// defeat the analysis that produces this result here. -template -T defeat_ssa(const T& t) -{ - return time(NULL) ? t : nullptr; -} - bool TestVPHooks(std::string &error) { GET_SHPTR(g_SHPtr); @@ -131,9 +118,9 @@ bool TestVPHooks(std::string &error) CDerived1 d1i2; CDerived2 d2i1; - IBase *p_d1i1 = defeat_ssa(&d1i1); - IBase *p_d1i2 = defeat_ssa(&d1i2); - IBase *p_d2i1 = defeat_ssa(&d2i1); + IBase *p_d1i1 = &d1i1; + IBase *p_d1i2 = &d1i2; + IBase *p_d2i1 = &d2i1; int hook1 = SH_ADD_VPHOOK(IBase, Func1, p_d1i1, SH_STATIC(Handler_Func1_Pre), false); diff --git a/utils/mmsource/core/version.rc b/utils/mmsource/core/version.rc index 63bde2b5..2e4420e5 100644 --- a/utils/mmsource/core/version.rc +++ b/utils/mmsource/core/version.rc @@ -27,8 +27,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION MMS_VERSION_FILE - PRODUCTVERSION MMS_VERSION_FILE + FILEVERSION MMS_FILE_VERSION + PRODUCTVERSION MMS_FILE_VERSION FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -45,12 +45,12 @@ BEGIN BEGIN VALUE "Comments", "Metamod: Source" VALUE "FileDescription", "Metamod: Source" - VALUE "FileVersion", MMS_VERSION_STRING + VALUE "FileVersion", MMS_FULL_VERSION VALUE "InternalName", "mmsource" VALUE "LegalCopyright", "Copyright (c) 2004-2010, Metamod: Source Development Team" VALUE "OriginalFilename", BINARY_NAME VALUE "ProductName", "Metamod:Source" - VALUE "ProductVersion", MMS_VERSION_STRING + VALUE "ProductVersion", MMS_FULL_VERSION END END BLOCK "VarFileInfo" diff --git a/utils/mmsource/core/vsp_bridge.cpp b/utils/mmsource/core/vsp_bridge.cpp index ba813fa6..b8e7cc7d 100644 --- a/utils/mmsource/core/vsp_bridge.cpp +++ b/utils/mmsource/core/vsp_bridge.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include "provider/provider_ep2.h" @@ -164,14 +164,11 @@ class VspBridge : public IVspBridge virtual void Unload() { - // Source2 doesn't have the Error function (nor VSP support). -#if SOURCE_ENGINE != SE_DOTA if (g_bIsTryingToUnload) { Error("Metamod:Source cannot be unloaded from VSP mode. Use \"meta unload\" to unload specific plugins.\n"); return; } -#endif if (g_plugin_unload != NULL) { SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads, false); diff --git a/utils/mmsource/loader/AMBuilder b/utils/mmsource/loader/AMBuilder index 7a4a991d..02073590 100644 --- a/utils/mmsource/loader/AMBuilder +++ b/utils/mmsource/loader/AMBuilder @@ -1,9 +1,8 @@ # vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: import os.path -def configure_library(name, linux_defines, arch): - libname = name - binary = MMS.Library(builder, libname, arch) +def configure_library(name, linux_defines): + binary = MMS.Library(builder, name) binary.compiler.cxxincludes += [os.path.join(builder.sourcePath, 'core', 'sourcehook')] binary.sources += [ 'loader.cpp', @@ -12,17 +11,12 @@ def configure_library(name, linux_defines, arch): 'utility.cpp', ] - if builder.target.platform == 'linux': + if builder.target_platform == 'linux': binary.compiler.defines += linux_defines nodes = builder.Add(binary) MMS.binaries += [nodes] -for arch in MMS.archs: - if builder.target.platform == 'linux': - if arch == 'x64': - configure_library('libserver', ['LIB_PREFIX="lib"', 'LIB_SUFFIX=".so"'], arch) - elif arch == 'x86': - configure_library('server_i486', ['LIB_PREFIX=""', 'LIB_SUFFIX="_i486.so"'], arch) - - configure_library('server', ['LIB_PREFIX="lib"', 'LIB_SUFFIX=".so"'], arch) +configure_library('server', ['LIB_PREFIX="lib"', 'LIB_SUFFIX=".so"']) +if builder.target_platform == 'linux': + configure_library('server_i486', ['LIB_PREFIX=""', 'LIB_SUFFIX="_i486.so"']) diff --git a/utils/mmsource/loader/gamedll.cpp b/utils/mmsource/loader/gamedll.cpp index 66b9c5d3..1d46c9f6 100644 --- a/utils/mmsource/loader/gamedll.cpp +++ b/utils/mmsource/loader/gamedll.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 sw=4 tw=99 noet : * ====================================================== * Metamod:Source - * Copyright (C) 2004-2015 AlliedModders LLC and authors. + * Copyright (C) 2004-2009 AlliedModders LLC and authors. * All rights reserved. * ====================================================== * @@ -36,7 +36,6 @@ #include "gamedll.h" class IServerGameDLL; -class ISource2ServerConfig; #define MAX_GAMEDLL_PATHS 10 @@ -48,40 +47,17 @@ static void *gamedll_libs[MAX_GAMEDLL_PATHS]; static unsigned int gamedll_path_count = 0; static void *gamedll_lib = NULL; static IServerGameDLL *gamedll_iface = NULL; -static ISource2ServerConfig *config_iface = NULL; static QueryValveInterface gamedll_qvi = NULL; static int gamedll_version = 0; static int isgd_shutdown_index = -1; -#if defined _WIN32 -static int is2sc_allowdedi_index = 21; -#endif static char mm_path[PLATFORM_MAX_PATH]; -static bool g_is_source2 = false; #if defined _WIN32 #define SERVER_NAME "server.dll" -#if defined _WIN64 -#define PLATFORM_NAME "win64" -#else -#define PLATFORM_NAME "win32" -#endif #elif defined __APPLE__ #define SERVER_NAME "server.dylib" -#if defined __amd64__ -#define PLATFORM_NAME "osx64" -#else -#define PLATFORM_NAME "osx32" -#endif #elif defined __linux__ -#if defined __amd64__ -// hackhack - source2 uses libserver as name on POSIX, but source1 x64 does not -// (but source1 x64 is also client-only right now so what-ev) -#define SERVER_NAME "libserver" LIB_SUFFIX -#define PLATFORM_NAME "linuxsteamrt64" -#else -#define SERVER_NAME "server" LIB_SUFFIX -#define PLATFORM_NAME "linuxsteamrt32" -#endif +#define SERVER_NAME "server" LIB_SUFFIX #endif static bool @@ -102,7 +78,7 @@ mm_DetectGameInformation() return false; } - if (!mm_ResolvePath(game_name, game_path, sizeof(game_path), g_is_source2)) + if (!mm_ResolvePath(game_name, game_path, sizeof(game_path))) { mm_LogFatal("Could not resolve path: %s", game_name); return false; @@ -111,25 +87,16 @@ mm_DetectGameInformation() FILE *fp; char gameinfo_path[PLATFORM_MAX_PATH]; - bool is_source2 = false; mm_PathFormat(gameinfo_path, sizeof(gameinfo_path), "%s/gameinfo.txt", game_path); if ((fp = fopen(gameinfo_path, "rt")) == NULL) { - // Try Source2 gameinfo - mm_PathFormat(gameinfo_path, sizeof(gameinfo_path), "%s/gameinfo.gi", game_path); - if ((fp = fopen(gameinfo_path, "rt")) == NULL) - { - mm_LogFatal("Could not read file: %s", gameinfo_path); - return false; - } - else - { - is_source2 = true; - } + mm_LogFatal("Could not read file: %s", gameinfo_path); + return false; } char temp_path[PLATFORM_MAX_PATH]; char cur_path[PLATFORM_MAX_PATH]; + getcwd(cur_path, sizeof(cur_path)); char *ptr; const char *lptr; @@ -161,20 +128,15 @@ mm_DetectGameInformation() else { ptr = val; - if (getcwd(cur_path, sizeof(cur_path))) - lptr = cur_path; - else - lptr = ""; + lptr = cur_path; } - const char *pRelPath = is_source2 ? "../../" : ""; - const char *pOSDir = is_source2 ? PLATFORM_NAME "/" : ""; if (stricmp(key, "GameBin") == 0) - mm_PathFormat(temp_path, sizeof(temp_path), "%s/%s%s/%s" SERVER_NAME, lptr, pRelPath, ptr, pOSDir); + mm_PathFormat(temp_path, sizeof(temp_path), "%s/%s/" SERVER_NAME, lptr, ptr); else if (!ptr[0]) - mm_PathFormat(temp_path, sizeof(temp_path), "%s/%sbin/%s" SERVER_NAME, lptr, pRelPath, pOSDir); + mm_PathFormat(temp_path, sizeof(temp_path), "%s/bin/" SERVER_NAME, lptr); else - mm_PathFormat(temp_path, sizeof(temp_path), "%s/%s%s/bin/%s" SERVER_NAME, lptr, pRelPath, ptr, pOSDir); + mm_PathFormat(temp_path, sizeof(temp_path), "%s/%s/bin/" SERVER_NAME, lptr, ptr); if (mm_PathCmp(mm_path, temp_path)) continue; @@ -212,7 +174,7 @@ mm_DetectGameInformation() if (gamedll_path_count == 0) { - mm_LogFatal("Could not detect any valid game paths in gameinfo file"); + mm_LogFatal("Could not detect any valid game paths in gameinfo.txt"); return false; } @@ -236,216 +198,13 @@ mm_PatchDllInit(bool patch); static void mm_PatchDllShutdown(); -#if defined _WIN32 -static void -mm_PatchAllowDedicated(bool patch); -#endif - -static void -mm_PatchConnect(bool patch); - static void *isgd_orig_init = NULL; static void *isgd_orig_shutdown = NULL; -#if defined _WIN32 -static void *is2sc_orig_allowdedi = NULL; -#endif -static void *is2sc_orig_connect = NULL; class VEmptyClass { }; -gamedll_bridge_info g_bridge_info; - -// Source2 - Rough start order -// CreateInterfaceFn (IS2SC) - hook Connect and AllowDedicatedServer -// IS2SC::Connect - save factory pointer. return orig. remove hook. -// IS2SC::AllowDedicatedServer - return true. remove hook. -// CreateInterfaceFn (IS2S) - hook Init and Shutdown -// IS2S::Init - do same as old ISGD::DLLInit, including core load. return orig. remove hook. -// IS2S::Shutdown - <-- this - -enum InitReturnVal_t -{ - INIT_FAILED = 0, - INIT_OK, - - INIT_LAST_VAL, -}; - -class ISource2ServerConfig -{ -public: - virtual bool Connect(QueryValveInterface factory) - { - g_bridge_info.engineFactory = factory; - g_bridge_info.fsFactory = factory; - g_bridge_info.physicsFactory = factory; - - - /* Call the original */ - bool result; - { - union - { - bool(VEmptyClass::*mfpnew)(QueryValveInterface factory); -#if defined _WIN32 - void *addr; - } u; - u.addr = is2sc_orig_connect; -#else - struct - { - void *addr; - intptr_t adjustor; - } s; - } u; - u.s.addr = is2sc_orig_connect; - u.s.adjustor = 0; -#endif - result = (((VEmptyClass *) config_iface)->*u.mfpnew)(factory); - } - - mm_PatchConnect(false); - - return result; - } -#if defined _WIN32 - virtual bool AllowDedicatedServers(int universe) const - { - mm_PatchAllowDedicated(false); - return true; - } -#endif -}; - -class ISource2Server -{ -public: - virtual bool Connect(QueryValveInterface factory) { return true; } - virtual void Disconnect() {} - virtual void *QueryInterface(const char *pInterfaceName) { return nullptr; } - - virtual InitReturnVal_t Init() - { - mm_backend = MMBackend_DOTA; - - char error[255]; - if (!mm_LoadMetamodLibrary(mm_backend, error, sizeof(error))) - { - mm_LogFatal("Detected engine %d but could not load: %s", mm_backend, error); - } - else - { - typedef IGameDllBridge *(*GetGameDllBridge)(); - GetGameDllBridge get_bridge = (GetGameDllBridge)mm_GetProcAddress("GetGameDllBridge"); - if (get_bridge == NULL) - { - mm_UnloadMetamodLibrary(); - mm_LogFatal("Detected engine %d but could not find GetGameDllBridge callback", mm_backend); - } - else - { - gamedll_bridge = get_bridge(); - } - } - - if (gamedll_bridge) - { - g_bridge_info.pGlobals = nullptr;// pGlobals; - g_bridge_info.dllVersion = gamedll_version; - g_bridge_info.isgd = gamedll_iface; - g_bridge_info.gsFactory = gamedll_qvi; - g_bridge_info.vsp_listener_path = mm_path; - - strcpy(error, "Unknown error"); - if (!gamedll_bridge->DLLInit_Pre(&g_bridge_info, error, sizeof(error))) - { - gamedll_bridge = NULL; - mm_UnloadMetamodLibrary(); - mm_LogFatal("Unknown error loading Metamod for engine %d: %s", mm_backend, error); - } - } - - /* Call the original */ - InitReturnVal_t result; - { - union - { - InitReturnVal_t(VEmptyClass::*mfpnew)(); -#if defined _WIN32 - void *addr; - } u; - u.addr = isgd_orig_init; -#else - struct - { - void *addr; - intptr_t adjustor; - } s; - } u; - u.s.addr = isgd_orig_init; - u.s.adjustor = 0; -#endif - result = (((VEmptyClass *)gamedll_iface)->*u.mfpnew)(); - } - - /** - * :TODO: possible logic hole here, what happens if the gamedll REALLY returns false? - * I'm pretty sure we'll die horribly. - */ - - if (!result) - { - gamedll_bridge->Unload(); - mm_UnloadMetamodLibrary(); - gamedll_bridge = NULL; - } - else if (gamedll_bridge != NULL) - { - gamedll_bridge->DLLInit_Post(&isgd_shutdown_index); - assert(isgd_shutdown_index != -1); - mm_PatchDllShutdown(); - } - - mm_PatchDllInit(false); - - return result; - } - - virtual void Shutdown() - { - gamedll_bridge->Unload(); - gamedll_bridge = NULL; - mm_UnloadMetamodLibrary(); - - /* Call original function */ - { - union - { - void (VEmptyClass::*mfpnew)(); -#if defined _WIN32 - void *addr; - } u; - u.addr = isgd_orig_shutdown; -#else - struct - { - void *addr; - intptr_t adjustor; - } s; - } u; - u.s.addr = isgd_orig_shutdown; - u.s.adjustor = 0; -#endif - (((VEmptyClass *)gamedll_iface)->*u.mfpnew)(); - } - - mm_UnloadLibrary(gamedll_lib); - gamedll_lib = NULL; - } -}; - class IServerGameDLL { public: @@ -485,17 +244,19 @@ class IServerGameDLL if (gamedll_bridge) { - g_bridge_info.engineFactory = (QueryValveInterface)engineFactory; - g_bridge_info.physicsFactory = (QueryValveInterface)physicsFactory; - g_bridge_info.fsFactory = (QueryValveInterface)fileSystemFactory; - g_bridge_info.pGlobals = pGlobals; - g_bridge_info.dllVersion = gamedll_version; - g_bridge_info.isgd = gamedll_iface; - g_bridge_info.gsFactory = gamedll_qvi; - g_bridge_info.vsp_listener_path = mm_path; + gamedll_bridge_info info; + + info.engineFactory = (QueryValveInterface)engineFactory; + info.physicsFactory = (QueryValveInterface)physicsFactory; + info.fsFactory = (QueryValveInterface)fileSystemFactory; + info.pGlobals = pGlobals; + info.dllVersion = gamedll_version; + info.isgd = gamedll_iface; + info.gsFactory = gamedll_qvi; + info.vsp_listener_path = mm_path; strcpy(error, "Unknown error"); - if (!gamedll_bridge->DLLInit_Pre(&g_bridge_info, error, sizeof(error))) + if (!gamedll_bridge->DLLInit_Pre(&info, error, sizeof(error))) { gamedll_bridge = NULL; mm_UnloadMetamodLibrary(); @@ -589,8 +350,6 @@ class IServerGameDLL }; static IServerGameDLL isgd_thunk; -static ISource2Server is2s_thunk; -static ISource2ServerConfig is2sc_thunk; static void mm_PatchDllInit(bool patch) @@ -599,27 +358,13 @@ mm_PatchDllInit(bool patch) void **vtable_dest; SourceHook::MemFuncInfo mfp; - if (g_is_source2) - { - SourceHook::GetFuncInfo(&ISource2Server::Init, mfp); - } - else - { - SourceHook::GetFuncInfo(&IServerGameDLL::DLLInit, mfp); - } + SourceHook::GetFuncInfo(&IServerGameDLL::DLLInit, mfp); assert(mfp.isVirtual); assert(mfp.thisptroffs == 0); assert(mfp.vtbloffs == 0); - if (g_is_source2) - { - vtable_src = (void **)*(void **)&is2s_thunk; - } - else - { - vtable_src = (void **)*(void **)&isgd_thunk; - } + vtable_src = (void **)*(void **)&isgd_thunk; vtable_dest = (void **)*(void **)gamedll_iface; SourceHook::SetMemAccess(&vtable_dest[mfp.vtblindex], @@ -648,169 +393,33 @@ mm_PatchDllShutdown() SourceHook::MemFuncInfo mfp; mfp.isVirtual = false; - if (g_is_source2) - { - SourceHook::GetFuncInfo(&ISource2Server::Shutdown, mfp); - } - else - { - SourceHook::GetFuncInfo(&IServerGameDLL::DLLShutdown, mfp); - } + SourceHook::GetFuncInfo(&IServerGameDLL::DLLShutdown, mfp); assert(mfp.isVirtual); assert(mfp.thisptroffs == 0); assert(mfp.vtbloffs == 0); - if (g_is_source2) - { - vtable_src = (void **)*(void **)&is2s_thunk; - } - else - { - vtable_src = (void **)*(void **)&isgd_thunk; - } + vtable_src = (void **)*(void **)&isgd_thunk; vtable_dest = (void **)*(void **)gamedll_iface; isgd_orig_shutdown = vtable_dest[isgd_shutdown_index]; vtable_dest[isgd_shutdown_index] = vtable_src[mfp.vtblindex]; } -#if defined _WIN32 static void -mm_PatchAllowDedicated(bool patch) +mm_PrepForGameLoad() { - void **vtable_src; - void **vtable_dest; - SourceHook::MemFuncInfo mfp; - - SourceHook::GetFuncInfo(&ISource2ServerConfig::AllowDedicatedServers, mfp); - - assert(mfp.isVirtual); - assert(mfp.thisptroffs == 0); - assert(mfp.vtbloffs == 0); - - vtable_src = (void **) *(void **) &is2sc_thunk; - vtable_dest = (void **) *(void **) config_iface; - - SourceHook::SetMemAccess(&vtable_dest[is2sc_allowdedi_index], - sizeof(void*), - SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC); - - if (patch) - { - assert(is2sc_orig_allowdedi == NULL); - is2sc_orig_allowdedi = vtable_dest[is2sc_allowdedi_index]; - vtable_dest[is2sc_allowdedi_index] = vtable_src[mfp.vtblindex]; - } - else - { - assert(is2sc_orig_allowdedi != NULL); - vtable_dest[is2sc_allowdedi_index] = is2sc_orig_allowdedi; - is2sc_orig_allowdedi = NULL; - } + mm_PatchDllInit(true); } -#endif - -static void -mm_PatchConnect(bool patch) -{ - void **vtable_src; - void **vtable_dest; - SourceHook::MemFuncInfo mfp; - - SourceHook::GetFuncInfo(&ISource2ServerConfig::Connect, mfp); - - assert(mfp.isVirtual); - assert(mfp.thisptroffs == 0); - assert(mfp.vtbloffs == 0); - - vtable_src = (void **) *(void **) &is2sc_thunk; - vtable_dest = (void **) *(void **) config_iface; - - SourceHook::SetMemAccess(&vtable_dest[mfp.vtblindex], - sizeof(void*), - SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC); - - if (patch) - { - assert(is2sc_orig_connect == NULL); - is2sc_orig_connect = vtable_dest[mfp.vtblindex]; - vtable_dest[mfp.vtblindex] = vtable_src[mfp.vtblindex]; - } - else - { - assert(is2sc_orig_connect != NULL); - vtable_dest[mfp.vtblindex] = is2sc_orig_connect; - is2sc_orig_connect = NULL; - } -} - void * mm_GameDllRequest(const char *name, int *ret) { - if (strncmp(name, "Source2ServerConfig", 19) == 0) + if (gamedll_lib != NULL && gamedll_bridge == NULL) { - g_is_source2 = true; - if (!mm_DetectGameInformation()) - { - if (ret != NULL) - *ret = 1; - return NULL; - } - - void *lib; - char error[255]; - void *ptr = NULL; - QueryValveInterface qvi; - for (unsigned int i = 0; i < gamedll_path_count; i++) - { - if (gamedll_libs[i] == NULL) - { - lib = mm_LoadLibrary(gamedll_paths[i], error, sizeof(error)); - if (lib == NULL) - continue; - gamedll_libs[i] = lib; - } - lib = gamedll_libs[i]; - qvi = (QueryValveInterface)mm_GetLibAddress(lib, "CreateInterface"); - if (qvi == NULL) - continue; - ptr = qvi(name, ret); - if (ptr != NULL) - { - gamedll_libs[i] = NULL; - break; - } - } - - if (ptr != NULL) - { - mm_FreeCachedLibraries(); - gamedll_lib = lib; - config_iface = (ISource2ServerConfig *) ptr; - gamedll_qvi = qvi; - - mm_PatchConnect(true); -#if defined _WIN32 - mm_PatchAllowDedicated(true); -#endif - - if (ret != NULL) - *ret = 0; - return ptr; - } + return gamedll_qvi(name, ret); } - else if (strncmp(name, "Source2Server0", 14) == 0) - { - gamedll_iface = (IServerGameDLL *)gamedll_qvi(name, ret); - gamedll_version = atoi(&name[13]); - mm_PatchDllInit(true); - if (ret != NULL) - *ret = 0; - return gamedll_iface; - } - else if (strncmp(name, "ServerGameDLL", 13) == 0) + if (strncmp(name, "ServerGameDLL", 13) == 0) { if (!mm_DetectGameInformation()) { @@ -851,17 +460,13 @@ mm_GameDllRequest(const char *name, int *ret) gamedll_iface = (IServerGameDLL *)ptr; gamedll_qvi = qvi; gamedll_version = atoi(&name[13]); - mm_PatchDllInit(true); + mm_PrepForGameLoad(); if (ret != NULL) *ret = 0; return ptr; } } - else if (gamedll_lib != NULL && gamedll_bridge == NULL) - { - return gamedll_qvi(name, ret); - } else if (game_info_detected == 0) { mm_LogFatal("Received interface request too early: %s", name); diff --git a/utils/mmsource/loader/loader.cpp b/utils/mmsource/loader/loader.cpp index e03d3d48..7e51d7ea 100644 --- a/utils/mmsource/loader/loader.cpp +++ b/utils/mmsource/loader/loader.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 sw=4 tw=99 noet : * ====================================================== * Metamod:Source - * Copyright (C) 2004-2015 AlliedModders LLC and authors. + * Copyright (C) 2004-2010 AlliedModders LLC and authors. * All rights reserved. * ====================================================== * @@ -68,7 +68,7 @@ mm_LogFatal(const char *message, ...) static const char *backend_names[] = { - "2.ep1", + "1.ep1", "2.darkm", "2.ep2", "2.bgt", @@ -115,12 +115,7 @@ mm_LoadMetamodLibrary(MetamodBackend backend, char *buffer, size_t maxlength) return false; len = strlen(mm_path); - - const char *pLastSlash = strrchr(mm_path, PATH_SEP_CHAR); - if (!pLastSlash) - return false; - - temp_len = strlen(&pLastSlash[1]); + temp_len = strlen("server" LIBRARY_EXT); if (len < temp_len) return false; @@ -152,7 +147,11 @@ mm_UnloadMetamodLibrary() #if defined _WIN32 #define EXPORT extern "C" __declspec(dllexport) #elif defined __GNUC__ +#if __GNUC__ >= 4 #define EXPORT extern "C" __attribute__ ((visibility("default"))) +#else +#define EXPORT extern "C" +#endif #endif EXPORT void * @@ -199,7 +198,6 @@ void mm_GetGameName(char *buffer, size_t size) { buffer[0] = '\0'; - bool bHasDedicated = false; #if defined _WIN32 static char game[128]; @@ -209,18 +207,15 @@ mm_GetGameName(char *buffer, size_t size) LPWSTR *wargv = CommandLineToArgvW(pCmdLine, &argc); for (int i = 0; i < argc; ++i) { - if (wcscmp(wargv[i], L"-game") == 0) - { - if (++i >= argc) - break; + if (wcscmp(wargv[i], L"-game") != 0) + continue; - wcstombs(buffer, wargv[i], size); - buffer[size-1] = '\0'; - } - else if (wcscmp(wargv[i], L"-dedicated") == 0) - { - bHasDedicated = true; - } + if (++i >= argc) + break; + + wcstombs(buffer, wargv[i], size); + buffer[size-1] = '\0'; + break; } LocalFree(wargv); @@ -230,18 +225,15 @@ mm_GetGameName(char *buffer, size_t size) char **argv = *_NSGetArgv(); for (int i = 0; i < argc; ++i) { - if (strcmp(argv[i], "-game") == 0) - { - if (++i >= argc) - break; + if (strcmp(argv[i], "-game") != 0) + continue; - strncpy(buffer, argv[i], size); - buffer[size-1] = '\0'; - } - else if (strcmp(argv[i], "-dedicated") == 0) - { - bHasDedicated = true; - } + if (++i >= argc) + break; + + strncpy(buffer, argv[i], size); + buffer[size-1] = '\0'; + break; } #elif defined __linux__ @@ -258,17 +250,13 @@ mm_GetGameName(char *buffer, size_t size) { strncpy(buffer, arg, size); buffer[size-1] = '\0'; - bNextIsGame = false; + break; } if (strcmp(arg, "-game") == 0) { bNextIsGame = true; } - else if (strcmp(arg, "-dedicated") == 0) - { - bHasDedicated = true; - } } free(arg); @@ -280,26 +268,18 @@ mm_GetGameName(char *buffer, size_t size) if (buffer[0] == 0) { - // HackHackHack - Different engines have different defaults if -game isn't specified - // we only use this for game detection, and not even in all cases. Old behavior was to - // give back ".", which was only really accurate for Dark Messiah. We'll add a special - // case for Source2 / Dota as well, since it only supports gameinfo loading, which relies - // on accuracy here more than VSP loading. - if (bHasDedicated) - { - strncpy(buffer, "dota", size); - } - else - { - strncpy(buffer, ".", size); - } + strncpy(buffer, ".", size); } } MetamodBackend mm_DetermineBackend(QueryValveInterface engineFactory, QueryValveInterface serverFactory, const char *game_name) { - if (engineFactory("VEngineServer023", NULL) != NULL) + if (engineFactory("VEngineServer024", NULL) != NULL) + { + return MMBackend_DOTA; + } + else if (engineFactory("VEngineServer023", NULL) != NULL) { if (engineFactory("EngineTraceServer004", NULL) == NULL) { diff --git a/utils/mmsource/loader/loader.h b/utils/mmsource/loader/loader.h index ca2e01d8..74ea9050 100644 --- a/utils/mmsource/loader/loader.h +++ b/utils/mmsource/loader/loader.h @@ -2,7 +2,7 @@ * vim: set ts=4 sw=4 tw=99 noet : * ====================================================== * Metamod:Source - * Copyright (C) 2004-2015 AlliedModders LLC and authors. + * Copyright (C) 2004-2009 AlliedModders LLC and authors. * All rights reserved. * ====================================================== * diff --git a/utils/mmsource/loader/utility.cpp b/utils/mmsource/loader/utility.cpp index 3733f394..5de2716b 100644 --- a/utils/mmsource/loader/utility.cpp +++ b/utils/mmsource/loader/utility.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 : * ====================================================== * Metamod:Source - * Copyright (C) 2004-2015 AlliedModders LLC and authors. + * Copyright (C) 2004-2008 AlliedModders LLC and authors. * All rights reserved. * ====================================================== * @@ -225,30 +225,6 @@ mm_KeySplit(const char *str, char *buf1, size_t len1, char *buf2, size_t len2) bool mm_PathCmp(const char *path1, const char *path2) { -#ifdef _WIN32 - char szFullPath1[PLATFORM_MAX_PATH]; - char szFullPath2[PLATFORM_MAX_PATH]; - if (GetFullPathName(path1, sizeof(szFullPath1), szFullPath1, nullptr) != 0) - { - path1 = szFullPath1; - } - if (GetFullPathName(path2, sizeof(szFullPath2), szFullPath2, nullptr) != 0) - { - path2 = szFullPath2; - } -#else - char szFullPath1[PATH_MAX + 1]; - char szFullPath2[PATH_MAX + 1]; - if (realpath(path1, szFullPath1)) - { - path1 = szFullPath1; - } - if (realpath(path2, szFullPath2)) - { - path2 = szFullPath2; - } -#endif - size_t pos1 = 0, pos2 = 0; while (true) @@ -299,14 +275,8 @@ mm_PathCmp(const char *path1, const char *path2) } bool -mm_ResolvePath(const char *path, char *buffer, size_t maxlength, bool bSource2) +mm_ResolvePath(const char *path, char *buffer, size_t maxlength) { - char tmp[PLATFORM_MAX_PATH]; - if (bSource2) - { - mm_Format(tmp, sizeof(tmp), "../../%s", path); - path = tmp; - } #if defined _WIN32 return _fullpath(buffer, path, maxlength) != NULL; #elif defined __linux__ || defined __APPLE__ diff --git a/utils/mmsource/loader/utility.h b/utils/mmsource/loader/utility.h index 25be3e65..c586d1b0 100644 --- a/utils/mmsource/loader/utility.h +++ b/utils/mmsource/loader/utility.h @@ -2,7 +2,7 @@ * vim: set ts=4 : * ====================================================== * Metamod:Source - * Copyright (C) 2004-2015 AlliedModders LLC and authors. + * Copyright (C) 2004-2008 AlliedModders LLC and authors. * All rights reserved. * ====================================================== * @@ -43,7 +43,7 @@ extern void mm_UnloadLibrary(void *lib); extern bool -mm_ResolvePath(const char *path, char *buffer, size_t maxlength, bool bSource2); +mm_ResolvePath(const char *path, char *buffer, size_t maxlength); extern size_t mm_PathFormat(char *buffer, size_t len, const char *fmt, ...); diff --git a/utils/mmsource/loader/version.rc b/utils/mmsource/loader/version.rc index 7de5c4d7..eb8e3444 100644 --- a/utils/mmsource/loader/version.rc +++ b/utils/mmsource/loader/version.rc @@ -27,8 +27,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION MMS_VERSION_FILE - PRODUCTVERSION MMS_VERSION_FILE + FILEVERSION MMS_FILE_VERSION + PRODUCTVERSION MMS_FILE_VERSION FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -45,12 +45,12 @@ BEGIN BEGIN VALUE "Comments", "Metamod: Source Loader" VALUE "FileDescription", "Metamod: Source Loader" - VALUE "FileVersion", MMS_VERSION_STRING + VALUE "FileVersion", MMS_FULL_VERSION VALUE "InternalName", "mmsource" VALUE "LegalCopyright", "Copyright (c) 2004-2010, Metamod: Source Development Team" VALUE "OriginalFilename", BINARY_NAME VALUE "ProductName", "Metamod:Source Loader" - VALUE "ProductVersion", MMS_VERSION_STRING + VALUE "ProductVersion", MMS_FULL_VERSION END END BLOCK "VarFileInfo" diff --git a/utils/mmsource/product.version b/utils/mmsource/product.version index 1f724bf4..ef3ef344 100644 --- a/utils/mmsource/product.version +++ b/utils/mmsource/product.version @@ -1 +1 @@ -1.11.0-dev +1.10.7-dev diff --git a/utils/mmsource/public/metamod_version.h b/utils/mmsource/public/metamod_version.h index 2fb3ac1e..d0d1fe13 100644 --- a/utils/mmsource/public/metamod_version.h +++ b/utils/mmsource/public/metamod_version.h @@ -33,34 +33,12 @@ */ #if defined MMS_GENERATED_BUILD -# if defined RC_COMPILE -# undef MMS_USE_VERSIONLIB -# endif -# if defined MMS_USE_VERSIONLIB -# include -# else -# include -# endif +#include #else -#define MMS_BUILD_TAG "manual" -#define MMS_BUILD_LOCAL_REV "0" -#define MMS_BUILD_CSET "0" -#define MMS_BUILD_MAJOR "1" -#define MMS_BUILD_MINOR "11" -#define MMS_BUILD_RELEASE "0" - -#define MMS_BUILD_UNIQUEID MMS_BUILD_LOCAL_REV ":" MMS_BUILD_CSET - -#define MMS_VERSION_STRING MMS_BUILD_MAJOR "." MMS_BUILD_MINOR "." MMS_BUILD_RELEASE "-" MMS_BUILD_TAG -#define MMS_VERSION_FILE 1,11,0,0 -#endif -#define MMS_BUILD_TIMESTAMP __DATE__ " " __TIME__ - -#if !defined(MMS_GENERATED_BUILD) || !defined(MMS_USE_VERSIONLIB) -# define METAMOD_VERSION MMS_VERSION_STRING -# define METAMOD_BUILD_ID MMS_BUILD_UNIQUEID -# define METAMOD_BUILD_TIME MMS_BUILD_TIMESTAMP +#define MMS_BUILD_STRING "-pdev" +#define MMS_BUILD_UNIQUEID "701:46ea970e0eb6" MMS_BUILD_STRING +#define MMS_FULL_VERSION "1.9.0" MMS_BUILD_STRING +#define MMS_FILE_VERSION 1,9,0,0 #endif #endif /* _INCLUDE_METAMOD_VERSION_INFORMATION_H_ */ - diff --git a/utils/mmsource/pushbuild.txt b/utils/mmsource/pushbuild.txt index c0bc9816..8d3f1741 100644 --- a/utils/mmsource/pushbuild.txt +++ b/utils/mmsource/pushbuild.txt @@ -1,5 +1,6 @@ MM:S and SM load on Portal on Mac OS X. How cool is that? It would be cool if the OS X package uploaded though. +Bleh. Burgledorfs and blaggermuffins are among the king's favorites. Ten ticket takers tackled two terrible tyrants. There once was a @@ -10,14 +11,15 @@ yur an IServerGameDLLLLL hats oh, i'll get it right this time I'd be angry. -rum hom! +rum hom bees bees bees? she calls it a mayonegg Why is Windows so awful? -cleng cling clang clung clong +cling clang clung javaliabuf +k egg. -pulled pork, yeah... +pulled pork, yeah.. king of the javalias ducks versus geese, who will win? more like g_pBad @@ -25,14 +27,7 @@ I didn't have any dreams. Eat your potato, Ricky! Buildbot shall pay the iron price. BMO Chop! If this was a real attack, you'd be dead. -Hey Morty! -jam clam! -her? -Confused clams claim clowns clobber clans containing cloaked clients. -Beads -We've have it all! -dvander is one million ladies tall today... +This.... +That....... Your tier1 tower is under attack.. -Christmas! -is Skinny Pete any relation to Sneaky Pete??? -where Travis? +Christmas! \ No newline at end of file diff --git a/utils/mmsource/sample_mm/Makefile b/utils/mmsource/sample_mm/Makefile index e948f4d0..d0ab2372 100644 --- a/utils/mmsource/sample_mm/Makefile +++ b/utils/mmsource/sample_mm/Makefile @@ -26,7 +26,7 @@ OBJECTS = sample_mm.cpp ############################################## OPT_FLAGS = -O3 -funroll-loops -pipe -GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 +GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden DEBUG_FLAGS = -g -ggdb3 -D_DEBUG CPP = gcc CPP_OSX = clang @@ -85,11 +85,7 @@ OS := $(shell uname -s) ifeq "$(OS)" "Darwin" LIB_EXT = dylib - ifeq "$(ENGINE)" "csgo" - HL2LIB = $(HL2SDK)/lib/osx64 - else - HL2LIB = $(HL2SDK)/lib/mac - endif + HL2LIB = $(HL2SDK)/lib/mac else LIB_EXT = so ifeq "$(ENGINE)" "original" @@ -115,25 +111,14 @@ else endif endif -ifeq "$(OS)" "Darwin" - ifeq "$(ENGINE)" "csgo" - STATIC_SUFFIX = - LIB_SUFFIX = .x64.$(LIB_EXT) - else - STATIC_SUFFIX = _i486 - endif -else - STATIC_SUFFIX = _i486 -endif - CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_BLOODYGOODTIME=4 -DSE_EYE=5 \ -DSE_CSS=6 -DSE_ORANGEBOXVALVE=7 -DSE_LEFT4DEAD=8 -DSE_LEFT4DEAD2=9 -DSE_ALIENSWARM=10 \ -DSE_PORTAL2=11 -DSE_CSGO=12 -LINK += $(HL2LIB)/tier1$(STATIC_SUFFIX).a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) $(LIB_PREFIX)tier0$(LIB_SUFFIX) +LINK += $(HL2LIB)/tier1_i486.a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) $(LIB_PREFIX)tier0$(LIB_SUFFIX) ifeq "$(ENGINE)" "csgo" - LINK += $(HL2LIB)/interfaces$(STATIC_SUFFIX).a + LINK += $(HL2LIB)/interfaces_i486.a endif INCLUDE += -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/mathlib -I$(HL2PUB)/vstdlib \ @@ -156,19 +141,12 @@ endif ifeq "$(OS)" "Darwin" CPP = $(CPP_OSX) LIB_EXT = dylib - CFLAGS += -DOSX -D_OSX -mmacosx-version-min=10.9 - LINK += -dynamiclib -lc++ -mmacosx-version-min=10.9 - ifeq "$(ENGINE)" "csgo" - CFLAGS += -m64 -DX64BITS -DPLATFORM_64BITS - LINK += -m64 - else - CFLAGS += -m32 - LINK += -m32 - endif + CFLAGS += -DOSX -D_OSX + LINK += -dynamiclib -lstdc++ -mmacosx-version-min=10.5 else LIB_EXT = so - CFLAGS += -D_LINUX -m32 - LINK += -shared -m32 + CFLAGS += -D_LINUX + LINK += -shared endif IS_CLANG := $(shell $(CPP) --version | head -1 | grep clang > /dev/null && echo "1" || echo "0") @@ -184,7 +162,7 @@ endif CFLAGS += -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \ -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \ -Dstrcmpi=strcasecmp -DCOMPILER_GCC -Wall -Wno-non-virtual-dtor -Wno-overloaded-virtual \ - -Werror -fPIC -fno-exceptions -fno-rtti -msse -fno-strict-aliasing + -Werror -fPIC -fno-exceptions -fno-rtti -msse -m32 -fno-strict-aliasing # Clang || GCC >= 4 ifeq "$(shell expr $(IS_CLANG) \| $(CPP_MAJOR) \>= 4)" "1" @@ -193,7 +171,7 @@ endif # Clang >= 3 || GCC >= 4.7 ifeq "$(shell expr $(IS_CLANG) \& $(CPP_MAJOR) \>= 3 \| $(CPP_MAJOR) \>= 4 \& $(CPP_MINOR) \>= 7)" "1" - CFLAGS += -Wno-delete-non-virtual-dtor -Wno-unused-private-field -Wno-deprecated-register + CFLAGS += -Wno-delete-non-virtual-dtor endif # OS is Linux and not using clang @@ -220,7 +198,7 @@ check: fi sample_mm: check $(OBJ_BIN) - $(CPP) $(INCLUDE) $(OBJ_BIN) $(LINK) -ldl -lm -o $(BIN_DIR)/$(BINARY) + $(CPP) $(INCLUDE) -m32 $(OBJ_BIN) $(LINK) -ldl -lm -o $(BIN_DIR)/$(BINARY) default: all diff --git a/utils/mmsource/sample_mm/sample_mm.cpp b/utils/mmsource/sample_mm/sample_mm.cpp index 01951aca..a9cd19c7 100644 --- a/utils/mmsource/sample_mm/sample_mm.cpp +++ b/utils/mmsource/sample_mm/sample_mm.cpp @@ -28,6 +28,7 @@ SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t * SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *, bool); #if SOURCE_ENGINE >= SE_ORANGEBOX +SH_DECL_HOOK2_void(IServerGameClients, NetworkIDValidated, SH_NOATTRIB, 0, const char *, const char *); SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *, const CCommand &); #else SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *); diff --git a/utils/mmsource/stub_mm/Makefile b/utils/mmsource/stub_mm/Makefile index 6060a30e..c8ed9328 100644 --- a/utils/mmsource/stub_mm/Makefile +++ b/utils/mmsource/stub_mm/Makefile @@ -26,7 +26,7 @@ OBJECTS = stub_mm.cpp ############################################## OPT_FLAGS = -O3 -funroll-loops -pipe -GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 +GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden DEBUG_FLAGS = -g -ggdb3 -D_DEBUG CPP = gcc CPP_OSX = clang @@ -85,11 +85,7 @@ OS := $(shell uname -s) ifeq "$(OS)" "Darwin" LIB_EXT = dylib - ifeq "$(ENGINE)" "csgo" - HL2LIB = $(HL2SDK)/lib/osx64 - else - HL2LIB = $(HL2SDK)/lib/mac - endif + HL2LIB = $(HL2SDK)/lib/mac else LIB_EXT = so ifeq "$(ENGINE)" "original" @@ -115,24 +111,14 @@ else endif endif -ifeq "$(OS)" "Darwin" - ifeq "$(ENGINE)" "csgo" - STATIC_SUFFIX = - else - STATIC_SUFFIX = _i486 - endif -else - STATIC_SUFFIX = _i486 -endif - CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_BLOODYGOODTIME=4 -DSE_EYE=5 \ -DSE_CSS=6 -DSE_ORANGEBOXVALVE=7 -DSE_LEFT4DEAD=8 -DSE_LEFT4DEAD2=9 -DSE_ALIENSWARM=10 \ -DSE_PORTAL2=11 -DSE_CSGO=12 -LINK += $(HL2LIB)/tier1$(STATIC_SUFFIX).a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) $(LIB_PREFIX)tier0$(LIB_SUFFIX) +LINK += $(HL2LIB)/tier1_i486.a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) $(LIB_PREFIX)tier0$(LIB_SUFFIX) ifeq "$(ENGINE)" "csgo" - LINK += $(HL2LIB)/interfaces$(STATIC_SUFFIX).a + LINK += $(HL2LIB)/interfaces_i486.a endif INCLUDE += -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/mathlib -I$(HL2PUB)/vstdlib \ @@ -152,22 +138,16 @@ else CFLAGS += $(OPT_FLAGS) endif + ifeq "$(OS)" "Darwin" CPP = $(CPP_OSX) LIB_EXT = dylib - CFLAGS += -DOSX -D_OSX -mmacosx-version-min=10.9 - LINK += -dynamiclib -lc++ -mmacosx-version-min=10.9 - ifeq "$(ENGINE)" "csgo" - CFLAGS += -m64 -DX64BITS -DPLATFORM_64BITS - LINK += -m64 - else - CFLAGS += -m32 - LINK += -m32 - endif + CFLAGS += -DOSX -D_OSX + LINK += -dynamiclib -lstdc++ -mmacosx-version-min=10.5 else LIB_EXT = so - CFLAGS += -D_LINUX -m32 - LINK += -shared -m32 + CFLAGS += -D_LINUX + LINK += -shared endif IS_CLANG := $(shell $(CPP) --version | head -1 | grep clang > /dev/null && echo "1" || echo "0") @@ -183,7 +163,7 @@ endif CFLAGS += -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \ -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \ -Dstrcmpi=strcasecmp -DCOMPILER_GCC -Wall -Wno-non-virtual-dtor -Wno-overloaded-virtual \ - -Werror -fPIC -fno-exceptions -fno-rtti -msse -fno-strict-aliasing + -Werror -fPIC -fno-exceptions -fno-rtti -msse -m32 -fno-strict-aliasing # Clang || GCC >= 4 ifeq "$(shell expr $(IS_CLANG) \| $(CPP_MAJOR) \>= 4)" "1" @@ -192,7 +172,7 @@ endif # Clang >= 3 || GCC >= 4.7 ifeq "$(shell expr $(IS_CLANG) \& $(CPP_MAJOR) \>= 3 \| $(CPP_MAJOR) \>= 4 \& $(CPP_MINOR) \>= 7)" "1" - CFLAGS += -Wno-delete-non-virtual-dtor -Wno-unused-private-field -Wno-deprecated-register + CFLAGS += -Wno-delete-non-virtual-dtor endif # OS is Linux and not using clang @@ -219,7 +199,7 @@ check: fi stub_mm: check $(OBJ_BIN) - $(CPP) $(INCLUDE) $(OBJ_BIN) $(LINK) -ldl -lm -o $(BIN_DIR)/$(BINARY) + $(CPP) $(INCLUDE) -m32 $(OBJ_BIN) $(LINK) -ldl -lm -o $(BIN_DIR)/$(BINARY) default: all diff --git a/utils/mmsource/support/buildbot/PackageScript b/utils/mmsource/support/buildbot/PackageScript index d6441267..a65ec7a6 100644 --- a/utils/mmsource/support/buildbot/PackageScript +++ b/utils/mmsource/support/buildbot/PackageScript @@ -7,31 +7,13 @@ addons_folder = builder.AddFolder('addons') metamod_folder = builder.AddFolder(os.path.join('addons', 'metamod')) bin_folder = builder.AddFolder(os.path.join('addons', 'metamod', 'bin')) -for arch in MMS.archs: - if arch == 'x64': - if builder.target.platform == 'windows': - bin64_folder = builder.AddFolder(os.path.join('addons', 'metamod', 'bin', 'win64')) - builder.AddCopy(os.path.join(builder.sourcePath, 'support', 'metamod_win64.vdf'), - os.path.join('addons', 'metamod_x64.vdf')) - elif builder.target.platform == 'linux': - bin64_folder = builder.AddFolder(os.path.join('addons', 'metamod', 'bin', 'linux64')) - builder.AddCopy(os.path.join(builder.sourcePath, 'support', 'metamod_linux64.vdf'), - os.path.join('addons', 'metamod_x64.vdf')) - elif builder.target.platform == 'mac': - bin64_folder = builder.AddFolder(os.path.join('addons', 'metamod', 'bin', 'osx64')) - builder.AddCopy(os.path.join(builder.sourcePath, 'support', 'metamod_osx64.vdf'), - os.path.join('addons', 'metamod_x64.vdf')) - builder.AddCopy(os.path.join(builder.sourcePath, 'support', 'metamod.vdf'), addons_folder) builder.AddCopy(os.path.join(builder.sourcePath, 'support', 'metaplugins.ini'), metamod_folder) builder.AddCopy(os.path.join(builder.sourcePath, 'support', 'README.txt'), metamod_folder) pdb_list = [] for task in MMS.binaries: - if '.x64' + os.sep in task.binary.path: - builder.AddCopy(task.binary, bin64_folder) - else: - builder.AddCopy(task.binary, bin_folder) + builder.AddCopy(task.binary, bin_folder) if task.debug: pdb_list.append(task.debug) diff --git a/utils/mmsource/support/buildbot/Versioning b/utils/mmsource/support/buildbot/Versioning index 1b5410fb..b02e378f 100644 --- a/utils/mmsource/support/buildbot/Versioning +++ b/utils/mmsource/support/buildbot/Versioning @@ -1,6 +1,5 @@ # vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: import os, sys -import re builder.SetBuildFolder('/') @@ -17,14 +16,11 @@ outputs = [ ] with open(os.path.join(builder.sourcePath, '.git', 'HEAD')) as fp: - head_contents = fp.read().strip() - if re.search('^[a-fA-F0-9]{40}$', head_contents): - git_head_path = os.path.join(builder.sourcePath, '.git', 'HEAD') - else: - git_state = head_contents.split(':')[1].strip() - git_head_path = os.path.join(builder.sourcePath, '.git', git_state) - if not os.path.exists(git_head_path): - git_head_path = os.path.join(builder.sourcePath, '.git', 'HEAD') + git_state = fp.read().strip().split(':')[1].strip() + +git_head_path = os.path.join(builder.sourcePath, '.git', git_state) +if not os.path.exists(git_head_path): + git_head_path = os.path.join(builder.sourcePath, '.git', 'HEAD') sources = [ os.path.join(builder.sourcePath, 'product.version'), diff --git a/utils/mmsource/support/buildbot/bootstrap.pl b/utils/mmsource/support/buildbot/bootstrap.pl index 740ee66c..7e352bb6 100644 --- a/utils/mmsource/support/buildbot/bootstrap.pl +++ b/utils/mmsource/support/buildbot/bootstrap.pl @@ -31,7 +31,6 @@ my @conf_argv = ( '--enable-optimize', - '--breakpad-dump', '--no-color', '--symbol-files' ); @@ -44,12 +43,6 @@ push(@conf_argv, '--hl2sdk-root=H:\\'); } -if ($^O !~ /MSWin/) { - push(@conf_argv, '--target-arch=x86,x64'); -} else { - push(@conf_argv, '--target-arch=x86'); -} - my $conf_args = join(' ', @conf_argv); if ($argn > 0 && $^O !~ /MSWin/) { diff --git a/utils/mmsource/support/buildbot/generate_headers.py b/utils/mmsource/support/buildbot/generate_headers.py index c730ee71..0135d2c1 100644 --- a/utils/mmsource/support/buildbot/generate_headers.py +++ b/utils/mmsource/support/buildbot/generate_headers.py @@ -55,32 +55,24 @@ def output_version_header(): if m == None: raise Exception('Could not detremine product version') major, minor, release, tag = m.groups() - product = "{0}.{1}.{2}".format(major, minor, release) - fullstring = product - if tag != "": - fullstring += "-{0}".format(tag) - if tag == "dev": - fullstring += "+{0}".format(count) + + if tag: + tag = '-' + tag with open(os.path.join(OutputFolder, 'metamod_version_auto.h'), 'w') as fp: - fp.write(""" -#ifndef _METAMOD_AUTO_VERSION_INFORMATION_H_ + fp.write("""#ifndef _METAMOD_AUTO_VERSION_INFORMATION_H_ #define _METAMOD_AUTO_VERSION_INFORMATION_H_ -#define MMS_BUILD_TAG \"{0}\" -#define MMS_BUILD_CSET \"{1}\" -#define MMS_BUILD_MAJOR \"{2}\" -#define MMS_BUILD_MINOR \"{3}\" -#define MMS_BUILD_RELEASE \"{4}\" -#define MMS_BUILD_LOCAL_REV \"{6}\" - -#define MMS_BUILD_UNIQUEID "{6}:" MMS_BUILD_CSET - -#define MMS_VERSION_STRING \"{5}\" -#define MMS_VERSION_FILE {2},{3},{4},0 +#define MMS_BUILD_STRING \"{0}\" +#define MMS_BUILD_LOCAL_REV \"{5}\" +#define MMS_BUILD_SHA \"{1}\" +#define MMS_BUILD_UNIQUEID \"{5}:{1}\" MMS_BUILD_STRING +#define MMS_FULL_VERSION \"{2}.{3}.{4}\" MMS_BUILD_STRING +#define MMS_FILE_VERSION {2},{3},{4},0 #endif /* _METAMOD_AUTO_VERSION_INFORMATION_H_ */ - """.format(tag, shorthash, major, minor, release, fullstring, count)) + +""".format(tag, shorthash, major, minor, release, count)) output_version_header() diff --git a/utils/mmsource/support/buildbot/package.pl b/utils/mmsource/support/buildbot/package.pl index 3a420b9c..6ba3d0bb 100644 --- a/utils/mmsource/support/buildbot/package.pl +++ b/utils/mmsource/support/buildbot/package.pl @@ -90,7 +90,7 @@ my ($ftp); -$ftp = Net::FTP->new($ftp_host, Debug => 0, Passive => 1) +$ftp = Net::FTP->new($ftp_host, Debug => 0, Passive => 1) or die "Cannot connect to host $ftp_host: $@"; $ftp->login($ftp_user, $ftp_pass) diff --git a/utils/mmsource/support/buildbot/startbuild.pl b/utils/mmsource/support/buildbot/startbuild.pl index 712ae630..38e6d011 100644 --- a/utils/mmsource/support/buildbot/startbuild.pl +++ b/utils/mmsource/support/buildbot/startbuild.pl @@ -10,12 +10,6 @@ chdir('../../../OUTPUT'); -my $argn = $#ARGV + 1; -if ($argn > 0) { - $ENV{CC} = $ARGV[0]; - $ENV{CXX} = $ARGV[0]; -} - system("ambuild --no-color 2>&1"); if ($? != 0) diff --git a/utils/mmsource/support/changelog.txt b/utils/mmsource/support/changelog.txt index f83610cf..c65e746e 100644 --- a/utils/mmsource/support/changelog.txt +++ b/utils/mmsource/support/changelog.txt @@ -1,3 +1,95 @@ +2015/09/17 1.10.6: + - Updated support for recent TF2, CS:S, DoD:S, and HL2:DM game updates. + +2014/05/30 1.10.5: + - Added support for Black Mesa (PR #14). + - Updated support for recent CS:GO game updates. + - Fixed game detection issues on Nuclear Dawn. + +2014/11/25 1.10.4: + - Updated support for recent TF2 game updates. + +2014/09/20 1.10.3: + - Updated support for recent TF2 and CS:GO game updates. + +2014/08/17 1.10.2: + - Fixed regression in Alien Swarm engine detection from version 1.10.1 (PR #6). + - Improved engine detection for more games when '-game' launching param is missing (PR #7). + +2014/07/03 1.10.1: + - Added support for Source SDK 2013 mods (bug 5916). + - Added support for Insurgency (bug 5950). + - Added support for Contagion (bug 6006). + - Added support for Blade Symphony (bug 5948). + - Updated Dota 2 support to add Linux and Mac OS X support (bug 6067). + - Improved engine detection when '-game' launch param is not present (bug 6020). + - Fixed a regression in engine detection for some cases (bug 5963). + +2013/08/25 1.10.0: + - Added support for Dota 2 on Windows. + - Split TF2, DoD:S, HL2:DM, and ND to separate binaries (bug 5667). + - Updated for latest games changes on HL2:DM, TF2, CS:S, DoD:S, L4D2, and Dota 2. + - Added basic VDF file for easier installation (bug 5681). + - Removed loader's reliance on tier0 by manually parsing command line for -game (bug 5674). + - Fixed MetamodVersionInfo::GetGameDir always returning NULL or garbage. + - Added META_NO_HL2SDK define to stop MM:S headers using the HL2SDK (bug 5079, bug 5469). + - Remove unused variables and defines (bug 5523). + - Fixed NULL conversion compile warning in loader. + +2013/02/06 1.9.2: + - Fixed load issues on CS:GO after protobuf networking game update (bug 5578). + - Fixed load issues on CS:S under linux after game update. + +2012/12/23 1.9.1: + - Fixed core-legacy crash on hook from making wrong page writable (bug 5533). + - Updated loader to attempt to guess correct tier0/vstdlib filenames on linux, fixing load on ep2v engine (bug 5522). + - Recompiled against new hl2sdk-ob-valve to fix vdf plugin loading on ep2v engine. + +2012/09/03 1.9.0: + - Added support for Counter-Strike: Global Offensive (bug 5228). + - Split Counter-Strike: Source to a separate build from 'ep2v' (SOURCE_ENGINE_CSS) (bug 5369). + - Fixed page protection bug causing a rare startup crash (bug 5133). + - Delayed unloading of plugins until it is absolutely safe (bug 5034). + - Fixed passage of non-literals as error and warning format strings. + +2011/06/23 1.8.7: + - Fixed libgcc_s.so.1 load error present on some systems (bug 4876). + - Metamod:Source will now work even when the Valve filesytem interface isn't + found (bug 4958). + +2011/04/15 1.8.6: + - Fixed compatibility with latest breaking Orange Box changes. + - Added support for Bloody Good Time (bug 4784). + +2010/12/19 1.8.5: + - Added support for latest Orange Box engine update (bug 4752). + +2010/10/30 1.8.4: + - Added support for Alien Swarm (bug 4529). + - Added support for L4D and L4D2 on Mac OS X (bug 4683 and bug 4646). + - Updated support for L4D (bug 4680). + - Fixed bug on OB listen servers where the engine was being detected as OBV + (bug 4560). + - Fixed hooking vtables with unaligned thunk entries and returning references + in manual hooks (bug 4655). + +2010/07/18 1.8.3: + - Added support for the latest L4D2 update (bug 4509). + - Fixed bug on OBV engine where extended plugins (such as SourceMod and + Stripper) could be given the wrong engine. (bug 4491). + - Fixed rare crash when certain engine libraries were loaded from an unexpected + location (bug 4475). + - Added MSVC 10.0 (Visual Studio 2010) project files for stub_mm and sample_mm + (bug 4520). + +2010/06/11 1.8.2: + - Added support for Mac OS X (bug 4391). + - Added support for CS:S on Orange Box (bug 4401). + - Platform suffix "_i486" is now optional for plugins (bug 4410). + +2010/05/02 1.8.1: + - Added support for latest L4D2 and Orange Box engine updates. + 2009/12/19 1.8.0: - Added support for the Source engine that runs Left 4 Dead 2 (bug 4078). - Added VP hook support to legacy SourceHook (bug 4019). diff --git a/utils/mmsource/versionlib/AMBuildScript b/utils/mmsource/versionlib/AMBuildScript index 0e239e4a..c52b2a07 100644 --- a/utils/mmsource/versionlib/AMBuildScript +++ b/utils/mmsource/versionlib/AMBuildScript @@ -1,16 +1,11 @@ # vim: sts=2 ts=8 sw=2 tw=99 et ft=python: -rvalue = {} -for arch in MMS.archs: - libname = 'version' - lib = MMS.StaticLibrary(builder, libname, arch) - lib.compiler.defines.remove('MMS_USE_VERSIONLIB') - lib.compiler.sourcedeps += MMS.generated_headers - lib.sources += [ - 'versionlib.cpp' - ] - - cmd = builder.Add(lib) - - rvalue[arch] = cmd.binary +lib = builder.compiler.StaticLibrary("version") +lib.compiler.sourcedeps += MMS.generated_headers +lib.sources += [ + 'versionlib.cpp' +] +cmd = builder.Add(lib) + +rvalue = cmd.binary diff --git a/utils/mmsource/versionlib/versionlib.cpp b/utils/mmsource/versionlib/versionlib.cpp index df5d6879..1a3fa87a 100644 --- a/utils/mmsource/versionlib/versionlib.cpp +++ b/utils/mmsource/versionlib/versionlib.cpp @@ -26,7 +26,7 @@ #include #include -const char *METAMOD_LOCAL_REV = MMS_BUILD_LOCAL_REV; -const char *METAMOD_SHA = MMS_BUILD_CSET; -const char *METAMOD_VERSION = MMS_VERSION_STRING; -const char *METAMOD_BUILD_TIME = __DATE__ " " __TIME__; +const char *METAMOD_BUILD_LOCAL_REV = MMS_BUILD_LOCAL_REV; +const char *METAMOD_BUILD_SHA = MMS_BUILD_SHA; +const char *METAMOD_VERSION = MMS_FULL_VERSION; + diff --git a/utils/mmsource/versionlib/versionlib.h b/utils/mmsource/versionlib/versionlib.h index 07a4c266..8fe0eabe 100644 --- a/utils/mmsource/versionlib/versionlib.h +++ b/utils/mmsource/versionlib/versionlib.h @@ -25,23 +25,8 @@ #ifndef _INCLUDE_METAMOD_VERSIONLIB_H_ #define _INCLUDE_METAMOD_VERSIONLIB_H_ -#if !defined(MMS_USE_VERSIONLIB) -// These get defined in metamod_version.h since -// versionlib does not use versionlib. -# undef METAMOD_LOCAL_REV -# undef METAMOD_CSET -# undef METAMOD_VERSION -# undef METAMOD_BUILD_TIME -#endif - -#ifdef __cplusplus -# define EXTERN_C extern "C" -#else -# define EXTERN_C extern -#endif -EXTERN_C const char *METAMOD_LOCAL_REV; -EXTERN_C const char *METAMOD_SHA; -EXTERN_C const char *METAMOD_VERSION; -EXTERN_C const char *METAMOD_BUILD_TIME; +extern "C" const char *METAMOD_BUILD_LOCAL_REV; +extern "C" const char *METAMOD_BUILD_SHA; +extern "C" const char *METAMOD_VERSION; #endif // _INCLUDE_METAMOD_VERSIONLIB_H_ diff --git a/utils/vprojtomake/makefilecreator.cpp b/utils/vprojtomake/makefilecreator.cpp new file mode 100644 index 00000000..e20b3ab4 --- /dev/null +++ b/utils/vprojtomake/makefilecreator.cpp @@ -0,0 +1,276 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "stdafx.h" +#include "makefilecreator.h" +#include "cmdlib.h" + +//----------------------------------------------------------------------------- +// Purpose: constructor +//----------------------------------------------------------------------------- +CMakefileCreator::CMakefileCreator() { + m_FileToBaseDirMapping.SetLessFunc( DefLessFunc( int ) ); +} + +//----------------------------------------------------------------------------- +// Purpose: destructor +//----------------------------------------------------------------------------- +CMakefileCreator::~CMakefileCreator() +{ +} + +void CMakefileCreator::CreateMakefiles( CVCProjConvert & proj ) +{ + m_ProjName = proj.GetName(); + m_BaseDir = proj.GetBaseDir(); + for ( int i = 0; i < proj.GetNumConfigurations(); i++ ) + { + m_FileToBaseDirMapping.RemoveAll(); + m_BuildDirectories.RemoveAll(); + m_BaseDirs.RemoveAll(); + + CreateMakefileName( proj.GetName().String(), proj.GetConfiguration(i) ); + CreateBaseDirs( proj.GetConfiguration(i) ); + FileHandle_t f = g_pFileSystem->Open( m_MakefileName.String(), "w+" ); + if ( !f ) + { + Warning( "failed to open %s for writing.\n", m_MakefileName.String() ); + continue; + } + OutputDirs(f); + OutputIncludes( proj.GetConfiguration(i), f ); + OutputObjLists( proj.GetConfiguration(i), f ); + OutputMainBuilder(f); + OutputBuildTarget(f); + g_pFileSystem->Close(f); + } +} + + +void CMakefileCreator::CreateBaseDirs( CVCProjConvert::CConfiguration & config ) +{ +// m_BaseDirs.Insert( "" ); + for ( int i = 0; i < config.GetNumFileNames(); i++ ) + { + if ( config.GetFileType(i) == CVCProjConvert::CConfiguration::FILE_SOURCE ) + { + char basedir[ MAX_PATH ]; + char fulldir[ MAX_PATH ]; + Q_snprintf( fulldir, sizeof(fulldir), "%s/%s", m_BaseDir.String(), config.GetFileName(i) ); + if ( Q_ExtractFilePath( fulldir, basedir, sizeof(basedir) ) ) + { + Q_FixSlashes( basedir ); + Q_StripTrailingSlash( basedir ); + int index = m_BaseDirs.Find( basedir ); + if ( index == m_BaseDirs.InvalidIndex() ) + { + index = m_BaseDirs.Insert( basedir ); + } + m_FileToBaseDirMapping.Insert(i, index ); + } + else + { + m_FileToBaseDirMapping.Insert(i, 0 ); + } + } + } +} + +void CMakefileCreator::CleanupFileName( char *name ) +{ + for ( int i = Q_strlen( name ) - 1; i >= 0; --i ) + { + if ( name[i] == ' ' || name[i] == '|' || name[i] == '\\' || name[i] == '/' || ( name[i] == '.' && i>=1 && name[i-1] == '.' )) + { + Q_memmove( &name[i], &name[i+1], Q_strlen( name ) - i - 1 ); + name[ Q_strlen( name ) - 1 ] = 0; + } + } +} + +void CMakefileCreator::CreateMakefileName( const char *projectName, CVCProjConvert::CConfiguration & config ) +{ + char makefileName[ MAX_PATH ]; + Q_snprintf( makefileName, sizeof(makefileName), "Makefile.%s_%s", projectName, config.GetName().String() ); + CleanupFileName( makefileName ); + m_MakefileName = makefileName; +} + +void CMakefileCreator::CreateDirectoryFriendlyName( const char *dirName, char *friendlyDirName, int friendlyDirNameSize ) +{ + Q_strncpy( friendlyDirName, dirName, friendlyDirNameSize ); + + int i; + for ( i = Q_strlen( friendlyDirName ) - 1; i >= 0; --i ) + { + if ( friendlyDirName[i] == '/' || friendlyDirName[i] == '\\' ) + { + friendlyDirName[i] = '_'; + } + if ( isalpha( friendlyDirName[i] ) ) + { + friendlyDirName[i] = toupper(friendlyDirName[i]); + } + if ( friendlyDirName[i] == '.' ) + { + Q_memmove( &friendlyDirName[i], &friendlyDirName[i+1], Q_strlen( friendlyDirName ) - i - 1 ); + friendlyDirName[ Q_strlen( friendlyDirName ) - 1 ] = 0; + } + } + + // strip any leading/trailing underscores + while ( friendlyDirName[0] == '_' && Q_strlen(friendlyDirName)>0 ) + { + Q_memmove( &friendlyDirName[0], &friendlyDirName[1], Q_strlen( friendlyDirName )- 1 ); + friendlyDirName[ Q_strlen( friendlyDirName ) - 1 ] = 0; + } + while ( Q_strlen(friendlyDirName)>0 && friendlyDirName[Q_strlen(friendlyDirName)-1] == '_' ) + { + friendlyDirName[ Q_strlen( friendlyDirName ) - 1 ] = 0; + } + + CleanupFileName( friendlyDirName ); +} + +void CMakefileCreator::CreateObjDirectoryFriendlyName ( char *name ) +{ +#ifdef _WIN32 + char *updir = "..\\"; +#else + char *updir = "../"; +#endif + + char *sep = Q_strstr( name, updir ); + while ( sep ) + { + Q_strcpy( sep, sep + strlen(updir) ); + sep = Q_strstr( sep, updir ); + } +} + +void CMakefileCreator::FileWrite( FileHandle_t f, const char *fmt, ... ) +{ + va_list args; + va_start(args, fmt); + char stringBuf[ 4096 ]; + Q_vsnprintf( stringBuf, sizeof(stringBuf), fmt, args ); + va_end(args); + g_pFileSystem->Write( stringBuf, Q_strlen(stringBuf), f ); +} + +void CMakefileCreator::OutputIncludes( CVCProjConvert::CConfiguration & config, FileHandle_t f ) +{ + FileWrite( f, "INCLUDES=" ); + for ( int i = 0; i < config.GetNumIncludes(); i++ ) + { + FileWrite( f, "-I%s ", config.GetInclude(i) ); + } + + for ( int i = 0; i < config.GetNumDefines(); i++ ) + { + FileWrite( f, "-D%s ", config.GetDefine(i) ); + } + FileWrite( f, "\n\n" ); +} + +void CMakefileCreator::OutputDirs( FileHandle_t f ) +{ + for ( int i = m_BaseDirs.First(); i != m_BaseDirs.InvalidIndex(); i = m_BaseDirs.Next(i) ) + { + const char *dirName = m_BaseDirs.GetElementName(i); + if ( !dirName || !Q_strlen(dirName) ) + { + dirName = m_BaseDir.String(); + } + + char friendlyDirName[ MAX_PATH ]; + CreateDirectoryFriendlyName( dirName, friendlyDirName, sizeof(friendlyDirName) ); + int dirLen = Q_strlen(friendlyDirName); + Q_strncat( friendlyDirName, "_SRC_DIR", sizeof(friendlyDirName), COPY_ALL_CHARACTERS ); + struct OutputDirMapping_t dirs; + dirs.m_SrcDir = friendlyDirName; + dirs.m_iBaseDirIndex = i; + friendlyDirName[ dirLen ] = 0; + Q_strncat( friendlyDirName, "_OBJ_DIR", sizeof(friendlyDirName), COPY_ALL_CHARACTERS ); + dirs.m_ObjDir = friendlyDirName; + friendlyDirName[ dirLen ] = 0; + Q_strncat( friendlyDirName, "_OBJS", sizeof(friendlyDirName), COPY_ALL_CHARACTERS ); + dirs.m_ObjName = friendlyDirName; + + char objDirName[ MAX_PATH ]; + Q_snprintf( objDirName, sizeof(objDirName) , "obj%c$(NAME)_$(ARCH)%c", CORRECT_PATH_SEPARATOR, CORRECT_PATH_SEPARATOR ); + Q_strncat( objDirName, dirName, sizeof(objDirName), COPY_ALL_CHARACTERS ); + CreateObjDirectoryFriendlyName( objDirName ); + dirs.m_ObjOutputDir = objDirName; + + m_BuildDirectories.AddToTail( dirs ); + + FileWrite( f, "%s=%s\n", dirs.m_SrcDir.String(), dirName ); + FileWrite( f, "%s=%s\n", dirs.m_ObjDir.String(), objDirName ); + } + FileWrite( f, "\n\n" ); +} + +void CMakefileCreator::OutputMainBuilder( FileHandle_t f ) +{ + int i; + FileWrite( f, "\n\nall: dirs $(NAME)_$(ARCH).$(SHLIBEXT)\n\n" ); + FileWrite( f, "dirs:\n" ); + for ( i = 0; i < m_BuildDirectories.Count(); i++ ) + { + FileWrite( f, "\t-mkdir -p $(%s)\n", m_BuildDirectories[i].m_ObjDir.String() ); + } + FileWrite( f, "\n\n" ); + + + FileWrite( f, "\n\n$(NAME)_$(ARCH).$(SHLIBEXT): " ); + for ( i = 0; i < m_BuildDirectories.Count(); i++ ) + { + FileWrite( f, "$(%s) ", m_BuildDirectories[i].m_ObjName.String() ); + } + FileWrite( f, "\n\t$(CLINK) $(SHLIBLDFLAGS) $(DEBUG) -o $(BUILD_DIR)/$@ " ); + for ( i = 0; i < m_BuildDirectories.Count(); i++ ) + { + FileWrite( f, "$(%s) ", m_BuildDirectories[i].m_ObjName.String() ); + } + FileWrite( f, "$(LDFLAGS) $(CPP_LIB)\n\n" ); +} + +void CMakefileCreator::OutputObjLists( CVCProjConvert::CConfiguration & config, FileHandle_t f ) +{ + for ( int buildDirIndex = 0; buildDirIndex < m_BuildDirectories.Count(); buildDirIndex++ ) + { + struct OutputDirMapping_t & dirs = m_BuildDirectories[buildDirIndex]; + FileWrite( f, "%s= \\\n", dirs.m_ObjName.String() ); + + for ( int j = m_FileToBaseDirMapping.FirstInorder(); j != m_FileToBaseDirMapping.InvalidIndex(); j = m_FileToBaseDirMapping.NextInorder(j) ) + { + if ( dirs.m_iBaseDirIndex == m_FileToBaseDirMapping[j] ) + { + char baseName[ MAX_PATH ]; + const char *fileName = config.GetFileName(m_FileToBaseDirMapping.Key(j)); + Q_FileBase( fileName, baseName, sizeof(baseName) ); + Q_SetExtension( baseName, ".o", sizeof(baseName) ); + + FileWrite( f, "\t$(%s)/%s \\\n", dirs.m_ObjDir.String(), baseName ); + } + } + FileWrite( f, "\n\n" ); + } + +} + +void CMakefileCreator::OutputBuildTarget( FileHandle_t f ) +{ + for( int i = 0; i < m_BuildDirectories.Count(); i++ ) + { + struct OutputDirMapping_t & dirs = m_BuildDirectories[i]; + FileWrite( f, "$(%s)/%%.o: $(%s)/%%.cpp\n", dirs.m_ObjDir.String(), dirs.m_SrcDir.String() ); + FileWrite( f, "\t$(DO_CC)\n\n"); + } + +} + diff --git a/utils/vprojtomake/makefilecreator.h b/utils/vprojtomake/makefilecreator.h new file mode 100644 index 00000000..2649359d --- /dev/null +++ b/utils/vprojtomake/makefilecreator.h @@ -0,0 +1,63 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#ifndef MAKEFILECREATOR_H +#define MAKEFILECREATOR_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "utlvector.h" +#include "utlsymbol.h" +#include "utldict.h" +#include "utlmap.h" +#include "vcprojconvert.h" +#include "filesystem.h" + +class CMakefileCreator +{ +public: + + CMakefileCreator(); + ~CMakefileCreator(); + + void CreateMakefiles( CVCProjConvert & proj ); + +private: + void CleanupFileName( char *name ); + void OutputDirs( FileHandle_t f ); + void OutputBuildTarget( FileHandle_t f ); + void OutputObjLists( CVCProjConvert::CConfiguration & config, FileHandle_t f ); + void OutputIncludes( CVCProjConvert::CConfiguration & config, FileHandle_t f ); + void OutputMainBuilder( FileHandle_t f ); + + void CreateBaseDirs( CVCProjConvert::CConfiguration & config ); + void CreateMakefileName( const char *projectName, CVCProjConvert::CConfiguration & config ); + void CreateDirectoryFriendlyName( const char *dirName, char *friendlyDirName, int friendlyDirNameSize ); + void CreateObjDirectoryFriendlyName ( char *name ); + void FileWrite( FileHandle_t f, const char *fmt, ... ); + + + CUtlDict m_BaseDirs; + CUtlMap m_FileToBaseDirMapping; + + struct OutputDirMapping_t + { + CUtlSymbol m_SrcDir; + CUtlSymbol m_ObjDir; + CUtlSymbol m_ObjName; + CUtlSymbol m_ObjOutputDir; + int m_iBaseDirIndex; + }; + + CUtlVector m_BuildDirectories; + CUtlSymbol m_MakefileName; + CUtlSymbol m_ProjName; + CUtlSymbol m_BaseDir; +}; + +#endif // MAKEFILECREATOR_H diff --git a/utils/vprojtomake/stdafx.cpp b/utils/vprojtomake/stdafx.cpp new file mode 100644 index 00000000..0a5d83d0 --- /dev/null +++ b/utils/vprojtomake/stdafx.cpp @@ -0,0 +1,15 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// stdafx.cpp : source file that includes just the standard includes +// classcheck.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/utils/vprojtomake/stdafx.h b/utils/vprojtomake/stdafx.h new file mode 100644 index 00000000..5c2a560d --- /dev/null +++ b/utils/vprojtomake/stdafx.h @@ -0,0 +1,26 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__50E4147E_A508_4D85_BF0A_BA26676063F0__INCLUDED_) +#define AFX_STDAFX_H__50E4147E_A508_4D85_BF0A_BA26676063F0__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__50E4147E_A508_4D85_BF0A_BA26676063F0__INCLUDED_) diff --git a/utils/vprojtomake/tinyxml/tinystr.cpp b/utils/vprojtomake/tinyxml/tinystr.cpp new file mode 100644 index 00000000..68125071 --- /dev/null +++ b/utils/vprojtomake/tinyxml/tinystr.cpp @@ -0,0 +1,116 @@ +/* +www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/* + * THIS FILE WAS ALTERED BY Tyge Løvset, 7. April 2005. + */ + + +#ifndef TIXML_USE_STL + +#include "tinystr.h" + +// Error value for find primitive +const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); + + +// Null rep. +TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; + + +void TiXmlString::reserve (size_type cap) +{ + if (cap > capacity()) + { + TiXmlString tmp; + tmp.init(length(), cap); + memcpy(tmp.start(), data(), length()); + swap(tmp); + } +} + + +TiXmlString& TiXmlString::assign(const char* str, size_type len) +{ + size_type cap = capacity(); + if (len > cap || cap > 3*(len + 8)) + { + TiXmlString tmp; + tmp.init(len); + memcpy(tmp.start(), str, len); + swap(tmp); + } + else + { + memmove(start(), str, len); + set_size(len); + } + return *this; +} + + +TiXmlString& TiXmlString::append(const char* str, size_type len) +{ + size_type newsize = length() + len; + if (newsize > capacity()) + { + reserve (newsize + capacity()); + } + memmove(finish(), str, len); + set_size(newsize); + return *this; +} + + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) +{ + TiXmlString tmp; + tmp.reserve(a.length() + b.length()); + tmp += a; + tmp += b; + return tmp; +} + +TiXmlString operator + (const TiXmlString & a, const char* b) +{ + TiXmlString tmp; + TiXmlString::size_type b_len = static_cast( strlen(b) ); + tmp.reserve(a.length() + b_len); + tmp += a; + tmp.append(b, b_len); + return tmp; +} + +TiXmlString operator + (const char* a, const TiXmlString & b) +{ + TiXmlString tmp; + TiXmlString::size_type a_len = static_cast( strlen(a) ); + tmp.reserve(a_len + b.length()); + tmp.append(a, a_len); + tmp += b; + return tmp; +} + + +#endif // TIXML_USE_STL diff --git a/utils/vprojtomake/tinyxml/tinystr.h b/utils/vprojtomake/tinyxml/tinystr.h new file mode 100644 index 00000000..3c2aa9d5 --- /dev/null +++ b/utils/vprojtomake/tinyxml/tinystr.h @@ -0,0 +1,319 @@ +/* +www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/* + * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. + * + * - completely rewritten. compact, clean, and fast implementation. + * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) + * - fixed reserve() to work as per specification. + * - fixed buggy compares operator==(), operator<(), and operator>() + * - fixed operator+=() to take a const ref argument, following spec. + * - added "copy" constructor with length, and most compare operators. + * - added swap(), clear(), size(), capacity(), operator+(). + */ + +#ifndef TIXML_USE_STL + +#ifndef TIXML_STRING_INCLUDED +#define TIXML_STRING_INCLUDED + +#include +#include + +/* The support for explicit isn't that universal, and it isn't really + required - it is used to check that the TiXmlString class isn't incorrectly + used. Be nice to old compilers and macro it here: +*/ +#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + #define TIXML_EXPLICIT explicit +#elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + #define TIXML_EXPLICIT explicit +#else + #define TIXML_EXPLICIT +#endif + + +/* + TiXmlString is an emulation of a subset of the std::string template. + Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. + Only the member functions relevant to the TinyXML project have been implemented. + The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase + a string and there's no more room, we allocate a buffer twice as big as we need. +*/ +class TiXmlString +{ + public : + // The size type used + typedef size_t size_type; + + // Error value for find primitive + static const size_type npos; // = -1; + + + // TiXmlString empty constructor + TiXmlString () : rep_(&nullrep_) + { + } + + // TiXmlString copy constructor + TiXmlString ( const TiXmlString & copy) : rep_(0) + { + init(copy.length()); + memcpy(start(), copy.data(), length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) + { + init( static_cast( strlen(copy) )); + memcpy(start(), copy, length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) + { + init(len); + memcpy(start(), str, len); + } + + // TiXmlString destructor + ~TiXmlString () + { + quit(); + } + + // = operator + TiXmlString& operator = (const char * copy) + { + return assign( copy, (size_type)strlen(copy)); + } + + // = operator + TiXmlString& operator = (const TiXmlString & copy) + { + return assign(copy.start(), copy.length()); + } + + + // += operator. Maps to append + TiXmlString& operator += (const char * suffix) + { + return append(suffix, static_cast( strlen(suffix) )); + } + + // += operator. Maps to append + TiXmlString& operator += (char single) + { + return append(&single, 1); + } + + // += operator. Maps to append + TiXmlString& operator += (const TiXmlString & suffix) + { + return append(suffix.data(), suffix.length()); + } + + + // Convert a TiXmlString into a null-terminated char * + const char * c_str () const { return rep_->str; } + + // Convert a TiXmlString into a char * (need not be null terminated). + const char * data () const { return rep_->str; } + + // Return the length of a TiXmlString + size_type length () const { return rep_->size; } + + // Alias for length() + size_type size () const { return rep_->size; } + + // Checks if a TiXmlString is empty + bool empty () const { return rep_->size == 0; } + + // Return capacity of string + size_type capacity () const { return rep_->capacity; } + + + // single char extraction + const char& at (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // [] operator + char& operator [] (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // find a char in a string. Return TiXmlString::npos if not found + size_type find (char lookup) const + { + return find(lookup, 0); + } + + // find a char in a string from an offset. Return TiXmlString::npos if not found + size_type find (char tofind, size_type offset) const + { + if (offset >= length()) return npos; + + for (const char* p = c_str() + offset; *p != '\0'; ++p) + { + if (*p == tofind) return static_cast< size_type >( p - c_str() ); + } + return npos; + } + + void clear () + { + //Lee: + //The original was just too strange, though correct: + // TiXmlString().swap(*this); + //Instead use the quit & re-init: + quit(); + init(0,0); + } + + /* Function to reserve a big amount of data when we know we'll need it. Be aware that this + function DOES NOT clear the content of the TiXmlString if any exists. + */ + void reserve (size_type cap); + + TiXmlString& assign (const char* str, size_type len); + + TiXmlString& append (const char* str, size_type len); + + void swap (TiXmlString& other) + { + Rep* r = rep_; + rep_ = other.rep_; + other.rep_ = r; + } + + private: + + void init(size_type sz) { init(sz, sz); } + void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } + char* start() const { return rep_->str; } + char* finish() const { return rep_->str + rep_->size; } + + struct Rep + { + size_type size, capacity; + char str[1]; + }; + + void init(size_type sz, size_type cap) + { + if (cap) + { + // Lee: the original form: + // rep_ = static_cast(operator new(sizeof(Rep) + cap)); + // doesn't work in some cases of new being overloaded. Switching + // to the normal allocation, although use an 'int' for systems + // that are overly picky about structure alignment. + const size_type bytesNeeded = sizeof(Rep) + cap; + const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); + rep_ = reinterpret_cast( new int[ intsNeeded ] ); + + rep_->str[ rep_->size = sz ] = '\0'; + rep_->capacity = cap; + } + else + { + rep_ = &nullrep_; + } + } + + void quit() + { + if (rep_ != &nullrep_) + { + // The rep_ is really an array of ints. (see the allocator, above). + // Cast it back before delete, so the compiler won't incorrectly call destructors. + delete [] ( reinterpret_cast( rep_ ) ); + } + } + + Rep * rep_; + static Rep nullrep_; + +} ; + + +inline bool operator == (const TiXmlString & a, const TiXmlString & b) +{ + return ( a.length() == b.length() ) // optimization on some platforms + && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare +} +inline bool operator < (const TiXmlString & a, const TiXmlString & b) +{ + return strcmp(a.c_str(), b.c_str()) < 0; +} + +inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } +inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } +inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } +inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } + +inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } +inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } +inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } +inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); +TiXmlString operator + (const TiXmlString & a, const char* b); +TiXmlString operator + (const char* a, const TiXmlString & b); + + +/* + TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. + Only the operators that we need for TinyXML have been developped. +*/ +class TiXmlOutStream : public TiXmlString +{ +public : + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const TiXmlString & in) + { + *this += in; + return *this; + } + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const char * in) + { + *this += in; + return *this; + } + +} ; + +#endif // TIXML_STRING_INCLUDED +#endif // TIXML_USE_STL diff --git a/utils/vprojtomake/tinyxml/tinyxml.cpp b/utils/vprojtomake/tinyxml/tinyxml.cpp new file mode 100644 index 00000000..9be6c6a6 --- /dev/null +++ b/utils/vprojtomake/tinyxml/tinyxml.cpp @@ -0,0 +1,1839 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include + +#ifdef TIXML_USE_STL +#include +#include +#endif + +#include "tinyxml.h" + +FILE* TiXmlFOpen( const char* filename, const char* mode ); + +bool TiXmlBase::condenseWhiteSpace = true; + +// Microsoft compiler security +FILE* TiXmlFOpen( const char* filename, const char* mode ) +{ + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filename, mode ); + if ( !err && fp ) + return fp; + return 0; + #else + return fopen( filename, mode ); + #endif +} + +void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) +{ + int i=0; + + while( i<(int)str.length() ) + { + unsigned char c = (unsigned char) str[i]; + + if ( c == '&' + && i < ( (int)str.length() - 2 ) + && str[i+1] == '#' + && str[i+2] == 'x' ) + { + // Hexadecimal character reference. + // Pass through unchanged. + // © -- copyright symbol, for example. + // + // The -1 is a bug fix from Rob Laveaux. It keeps + // an overflow from happening if there is no ';'. + // There are actually 2 ways to exit this loop - + // while fails (error case) and break (semicolon found). + // However, there is no mechanism (currently) for + // this function to return an error. + while ( i<(int)str.length()-1 ) + { + outString->append( str.c_str() + i, 1 ); + ++i; + if ( str[i] == ';' ) + break; + } + } + else if ( c == '&' ) + { + outString->append( entity[0].str, entity[0].strLength ); + ++i; + } + else if ( c == '<' ) + { + outString->append( entity[1].str, entity[1].strLength ); + ++i; + } + else if ( c == '>' ) + { + outString->append( entity[2].str, entity[2].strLength ); + ++i; + } + else if ( c == '\"' ) + { + outString->append( entity[3].str, entity[3].strLength ); + ++i; + } + else if ( c == '\'' ) + { + outString->append( entity[4].str, entity[4].strLength ); + ++i; + } + else if ( c < 32 ) + { + // Easy pass at non-alpha/numeric/symbol + // Below 32 is symbolic. + char buf[ 32 ]; + + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); + #else + sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); + #endif + + //*ME: warning C4267: convert 'size_t' to 'int' + //*ME: Int-Cast to make compiler happy ... + outString->append( buf, (int)strlen( buf ) ); + ++i; + } + else + { + //char realc = (char) c; + //outString->append( &realc, 1 ); + *outString += (char) c; // somewhat more efficient function call. + ++i; + } + } +} + + +TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() +{ + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; +} + + +TiXmlNode::~TiXmlNode() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } +} + + +void TiXmlNode::CopyTo( TiXmlNode* target ) const +{ + target->SetValue (value.c_str() ); + target->userData = userData; + target->location = location; +} + + +void TiXmlNode::Clear() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } + + firstChild = 0; + lastChild = 0; +} + + +TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) +{ + assert( node->parent == 0 || node->parent == this ); + assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); + + if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + delete node; + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + node->parent = this; + + node->prev = lastChild; + node->next = 0; + + if ( lastChild ) + lastChild->next = node; + else + firstChild = node; // it was an empty list. + + lastChild = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) +{ + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + + return LinkEndChild( node ); +} + + +TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) +{ + if ( !beforeThis || beforeThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + if ( beforeThis->prev ) + { + beforeThis->prev->next = node; + } + else + { + assert( firstChild == beforeThis ); + firstChild = node; + } + beforeThis->prev = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) +{ + if ( !afterThis || afterThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + if ( afterThis->next ) + { + afterThis->next->prev = node; + } + else + { + assert( lastChild == afterThis ); + lastChild = node; + } + afterThis->next = node; + return node; +} + + +TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) +{ + if ( !replaceThis ) + return 0; + + if ( replaceThis->parent != this ) + return 0; + + if ( withThis.ToDocument() ) { + // A document can never be a child. Thanks to Noam. + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = withThis.Clone(); + if ( !node ) + return 0; + + node->next = replaceThis->next; + node->prev = replaceThis->prev; + + if ( replaceThis->next ) + replaceThis->next->prev = node; + else + lastChild = node; + + if ( replaceThis->prev ) + replaceThis->prev->next = node; + else + firstChild = node; + + delete replaceThis; + node->parent = this; + return node; +} + + +bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) +{ + if ( !removeThis ) { + return false; + } + + if ( removeThis->parent != this ) + { + assert( 0 ); + return false; + } + + if ( removeThis->next ) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; + + if ( removeThis->prev ) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; + + delete removeThis; + return true; +} + +const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild(); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling(); + } +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild( val ); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } +} + + +const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = next; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = prev; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +void TiXmlElement::RemoveAttribute( const char * name ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING str( name ); + TiXmlAttribute* node = attributeSet.Find( str ); + #else + TiXmlAttribute* node = attributeSet.Find( name ); + #endif + if ( node ) + { + attributeSet.Remove( node ); + delete node; + } +} + +const TiXmlElement* TiXmlNode::FirstChildElement() const +{ + const TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = FirstChild( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement() const +{ + const TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = NextSibling( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlDocument* TiXmlNode::GetDocument() const +{ + const TiXmlNode* node; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + + +TiXmlElement::TiXmlElement (const char * _value) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} + + +#ifdef TIXML_USE_STL +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} +#endif + + +TiXmlElement::TiXmlElement( const TiXmlElement& copy) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + copy.CopyTo( this ); +} + + +void TiXmlElement::operator=( const TiXmlElement& base ) +{ + ClearThis(); + base.CopyTo( this ); +} + + +TiXmlElement::~TiXmlElement() +{ + ClearThis(); +} + + +void TiXmlElement::ClearThis() +{ + Clear(); + while( attributeSet.First() ) + { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove( node ); + delete node; + } +} + + +const char* TiXmlElement::Attribute( const char* name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return node->Value(); + return 0; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( attrib ) + return &attrib->ValueStr(); + return 0; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, int* i ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; + + if ( attrib ) { + result = attrib->Value(); + if ( i ) { + attrib->QueryIntValue( i ); + } + } + return result; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const std::string* result = 0; + + if ( attrib ) { + result = &attrib->ValueStr(); + if ( i ) { + attrib->QueryIntValue( i ); + } + } + return result; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, double* d ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; + + if ( attrib ) { + result = attrib->Value(); + if ( d ) { + attrib->QueryDoubleValue( d ); + } + } + return result; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const std::string* result = 0; + + if ( attrib ) { + result = &attrib->ValueStr(); + if ( d ) { + attrib->QueryDoubleValue( d ); + } + } + return result; +} +#endif + + +int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryIntValue( ival ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryIntValue( ival ); +} +#endif + + +int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryDoubleValue( dval ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryDoubleValue( dval ); +} +#endif + + +void TiXmlElement::SetAttribute( const char * name, int val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetIntValue( val ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, int val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetIntValue( val ); + } +} +#endif + + +void TiXmlElement::SetDoubleAttribute( const char * name, double val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetDoubleValue( val ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetDoubleValue( val ); + } +} +#endif + + +void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); + if ( attrib ) { + attrib->SetValue( cvalue ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); + if ( attrib ) { + attrib->SetValue( _value ); + } +} +#endif + + +void TiXmlElement::Print( FILE* cfile, int depth ) const +{ + int i; + assert( cfile ); + for ( i=0; iNext() ) + { + fprintf( cfile, " " ); + attrib->Print( cfile, depth ); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a node + // 2) An element with only a text child is printed as text + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if ( !firstChild ) + { + fprintf( cfile, " />" ); + } + else if ( firstChild == lastChild && firstChild->ToText() ) + { + fprintf( cfile, ">" ); + firstChild->Print( cfile, depth + 1 ); + fprintf( cfile, "", value.c_str() ); + } + else + { + fprintf( cfile, ">" ); + + for ( node = firstChild; node; node=node->NextSibling() ) + { + if ( !node->ToText() ) + { + fprintf( cfile, "\n" ); + } + node->Print( cfile, depth+1 ); + } + fprintf( cfile, "\n" ); + for( i=0; i", value.c_str() ); + } +} + + +void TiXmlElement::CopyTo( TiXmlElement* target ) const +{ + // superclass: + TiXmlNode::CopyTo( target ); + + // Element class: + // Clone the attributes, then clone the children. + const TiXmlAttribute* attribute = 0; + for( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next() ) + { + target->SetAttribute( attribute->Name(), attribute->Value() ); + } + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + +bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this, attributeSet.First() ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement( Value() ); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +const char* TiXmlElement::GetText() const +{ + const TiXmlNode* child = this->FirstChild(); + if ( child ) { + const TiXmlText* childText = child->ToText(); + if ( childText ) { + return childText->Value(); + } + } + return 0; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + ClearError(); +} + +TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} + + +#ifdef TIXML_USE_STL +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} +#endif + + +TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDocument::operator=( const TiXmlDocument& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) +{ + return LoadFile( Value(), encoding ); +} + + +bool TiXmlDocument::SaveFile() const +{ + return SaveFile( Value() ); +} + +bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) +{ + TIXML_STRING filename( _filename ); + value = filename; + + // reading in binary mode so that tinyxml can normalize the EOL + FILE* file = TiXmlFOpen( value.c_str (), "rb" ); + + if ( file ) + { + bool result = LoadFile( file, encoding ); + fclose( file ); + return result; + } + else + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } +} + +bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) +{ + if ( !file ) + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Delete the existing data: + Clear(); + location.Clear(); + + // Get the file size, so we can pre-allocate the string. HUGE speed impact. + long length = 0; + fseek( file, 0, SEEK_END ); + length = ftell( file ); + fseek( file, 0, SEEK_SET ); + + // Strange case, but good to handle up front. + if ( length <= 0 ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Subtle bug here. TinyXml did use fgets. But from the XML spec: + // 2.11 End-of-Line Handling + // + // + // ...the XML processor MUST behave as if it normalized all line breaks in external + // parsed entities (including the document entity) on input, before parsing, by translating + // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to + // a single #xA character. + // + // + // It is not clear fgets does that, and certainly isn't clear it works cross platform. + // Generally, you expect fgets to translate from the convention of the OS to the c/unix + // convention, and not work generally. + + /* + while( fgets( buf, sizeof(buf), file ) ) + { + data += buf; + } + */ + + char* buf = new char[ length+1 ]; + buf[0] = 0; + + if ( fread( buf, length, 1, file ) != 1 ) { + delete [] buf; + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Process the buffer in place to normalize new lines. (See comment above.) + // Copies from the 'p' to 'q' pointer, where p can advance faster if + // a newline-carriage return is hit. + // + // Wikipedia: + // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or + // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... + // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others + // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS + // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 + + const char* p = buf; // the read head + char* q = buf; // the write head + const char CR = 0x0d; + const char LF = 0x0a; + + buf[length] = 0; + while( *p ) { + assert( p < (buf+length) ); + assert( q <= (buf+length) ); + assert( q <= p ); + + if ( *p == CR ) { + *q++ = LF; + p++; + if ( *p == LF ) { // check for CR+LF (and skip LF) + p++; + } + } + else { + *q++ = *p++; + } + } + assert( q <= (buf+length) ); + *q = 0; + + Parse( buf, 0, encoding ); + + delete [] buf; + return !Error(); +} + + +bool TiXmlDocument::SaveFile( const char * filename ) const +{ + // The old c stuff lives on... + FILE* fp = TiXmlFOpen( filename, "w" ); + if ( fp ) + { + bool result = SaveFile( fp ); + fclose( fp ); + return result; + } + return false; +} + + +bool TiXmlDocument::SaveFile( FILE* fp ) const +{ + if ( useMicrosoftBOM ) + { + const unsigned char TIXML_UTF_LEAD_0 = 0xefU; + const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; + const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + + fputc( TIXML_UTF_LEAD_0, fp ); + fputc( TIXML_UTF_LEAD_1, fp ); + fputc( TIXML_UTF_LEAD_2, fp ); + } + Print( fp, 0 ); + return (ferror(fp) == 0); +} + + +void TiXmlDocument::CopyTo( TiXmlDocument* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->error = error; + target->errorId = errorId; + target->errorDesc = errorDesc; + target->tabsize = tabsize; + target->errorLocation = errorLocation; + target->useMicrosoftBOM = useMicrosoftBOM; + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + + +TiXmlNode* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlDocument::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + node->Print( cfile, depth ); + fprintf( cfile, "\n" ); + } +} + + +bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +const TiXmlAttribute* TiXmlAttribute::Next() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} + +/* +TiXmlAttribute* TiXmlAttribute::Next() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} +*/ + +const TiXmlAttribute* TiXmlAttribute::Previous() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} + +/* +TiXmlAttribute* TiXmlAttribute::Previous() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} +*/ + +void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + TIXML_STRING n, v; + + EncodeString( name, &n ); + EncodeString( value, &v ); + + if (value.find ('\"') == TIXML_STRING::npos) { + if ( cfile ) { + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; + } + } + else { + if ( cfile ) { + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; + } + } +} + + +int TiXmlAttribute::QueryIntValue( int* ival ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +int TiXmlAttribute::QueryDoubleValue( double* dval ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +void TiXmlAttribute::SetIntValue( int _value ) +{ + char buf [64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); + #else + sprintf (buf, "%d", _value); + #endif + SetValue (buf); +} + +void TiXmlAttribute::SetDoubleValue( double _value ) +{ + char buf [256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); + #else + sprintf (buf, "%g", _value); + #endif + SetValue (buf); +} + +int TiXmlAttribute::IntValue() const +{ + return atoi (value.c_str ()); +} + +double TiXmlAttribute::DoubleValue() const +{ + return atof (value.c_str ()); +} + + +TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlComment::operator=( const TiXmlComment& base ) +{ + Clear(); + base.CopyTo( this ); +} + + +void TiXmlComment::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlComment::CopyTo( TiXmlComment* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlText::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + if ( cdata ) + { + int i; + fprintf( cfile, "\n" ); + for ( i=0; i\n", value.c_str() ); // unformatted output + } + else + { + TIXML_STRING buffer; + EncodeString( value, &buffer ); + fprintf( cfile, "%s", buffer.c_str() ); + } +} + + +void TiXmlText::CopyTo( TiXmlText* target ) const +{ + TiXmlNode::CopyTo( target ); + target->cdata = cdata; +} + + +bool TiXmlText::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText( "" ); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration( const char * _version, + const char * _encoding, + const char * _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} + + +#ifdef TIXML_USE_STL +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} +#endif + + +TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + if ( cfile ) fprintf( cfile, "" ); + if ( str ) (*str) += "?>"; +} + + +void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->version = version; + target->encoding = encoding; + target->standalone = standalone; +} + + +bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlUnknown::Print( FILE* cfile, int depth ) const +{ + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlAttributeSet::TiXmlAttributeSet() +{ + sentinel.next = &sentinel; + sentinel.prev = &sentinel; +} + + +TiXmlAttributeSet::~TiXmlAttributeSet() +{ + assert( sentinel.next == &sentinel ); + assert( sentinel.prev == &sentinel ); +} + + +void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) +{ + #ifdef TIXML_USE_STL + assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. + #else + assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. + #endif + + addMe->next = &sentinel; + addMe->prev = sentinel.prev; + + sentinel.prev->next = addMe; + sentinel.prev = addMe; +} + +void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) +{ + TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node == removeMe ) + { + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = 0; + node->prev = 0; + return; + } + } + assert( 0 ); // we tried to remove a non-linked attribute. +} + + +#ifdef TIXML_USE_STL +TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} + +TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) +{ + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; +} +#endif + + +TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} + + +TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) +{ + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; +} + + +#ifdef TIXML_USE_STL +std::istream& operator>> (std::istream & in, TiXmlNode & base) +{ + TIXML_STRING tag; + tag.reserve( 8 * 1000 ); + base.StreamIn( &in, &tag ); + + base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); + return in; +} +#endif + + +#ifdef TIXML_USE_STL +std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out << printer.Str(); + + return out; +} + + +std::string& operator<< (std::string& out, const TiXmlNode& base ) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out.append( printer.Str() ); + + return out; +} +#endif + + +TiXmlHandle TiXmlHandle::FirstChild() const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement() const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild(); + for ( i=0; + child && iNextSibling(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild( value ); + for ( i=0; + child && iNextSibling( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement(); + for ( i=0; + child && iNextSiblingElement(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement( value ); + for ( i=0; + child && iNextSiblingElement( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) +{ + DoIndent(); + buffer += "<"; + buffer += element.Value(); + + for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) + { + buffer += " "; + attrib->Print( 0, 0, &buffer ); + } + + if ( !element.FirstChild() ) + { + buffer += " />"; + DoLineBreak(); + } + else + { + buffer += ">"; + if ( element.FirstChild()->ToText() + && element.LastChild() == element.FirstChild() + && element.FirstChild()->ToText()->CDATA() == false ) + { + simpleTextPrint = true; + // no DoLineBreak()! + } + else + { + DoLineBreak(); + } + } + ++depth; + return true; +} + + +bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) +{ + --depth; + if ( !element.FirstChild() ) + { + // nothing. + } + else + { + if ( simpleTextPrint ) + { + simpleTextPrint = false; + } + else + { + DoIndent(); + } + buffer += ""; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlText& text ) +{ + if ( text.CDATA() ) + { + DoIndent(); + buffer += ""; + DoLineBreak(); + } + else if ( simpleTextPrint ) + { + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + } + else + { + DoIndent(); + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) +{ + DoIndent(); + declaration.Print( 0, 0, &buffer ); + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlComment& comment ) +{ + DoIndent(); + buffer += ""; + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) +{ + DoIndent(); + buffer += "<"; + buffer += unknown.Value(); + buffer += ">"; + DoLineBreak(); + return true; +} + diff --git a/utils/vprojtomake/tinyxml/tinyxml.h b/utils/vprojtomake/tinyxml/tinyxml.h new file mode 100644 index 00000000..01822911 --- /dev/null +++ b/utils/vprojtomake/tinyxml/tinyxml.h @@ -0,0 +1,1799 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#ifndef TINYXML_INCLUDED +#define TINYXML_INCLUDED + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4530 ) +#pragma warning( disable : 4786 ) +#endif + +#include +#include +#include +#include +#include + +// Help out windows: +#if defined( _DEBUG ) && !defined( DEBUG ) +#define DEBUG +#endif + +#ifdef TIXML_USE_STL + #include + #include + #include + #define TIXML_STRING std::string +#else + #include "tinystr.h" + #define TIXML_STRING TiXmlString +#endif + +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE +#define TIXML_SAFE + +#ifdef TIXML_SAFE + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + // Microsoft visual studio, version 2005 and higher. + #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SSCANF sscanf_s + #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + //#pragma message( "Using _sn* functions." ) + #define TIXML_SNPRINTF _snprintf + #define TIXML_SSCANF sscanf + #elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf + #else + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf + #endif +#endif + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; +class TiXmlParsingData; + +const int TIXML_MAJOR_VERSION = 2; +const int TIXML_MINOR_VERSION = 6; +const int TIXML_PATCH_VERSION = 1; + +/* Internal structure for tracking location of items + in the XML file. +*/ +struct TiXmlCursor +{ + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } + + int row; // 0 based. + int col; // 0 based. +}; + + +/** + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a TiXmlVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves + are simply called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its sibilings will be Visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. + + You should never change the document from a callback. + + @sa TiXmlNode::Accept() +*/ +class TiXmlVisitor +{ +public: + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } + /// Visit a text node + virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } + /// Visit an unknow node + virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } +}; + +// Only used by Attribute::Query functions +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; + + +// Used by the parsing routines. +enum TiXmlEncoding +{ + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; + +const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; + +/** TiXmlBase is a base class for every class in TinyXml. + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + A Decleration contains: Attributes (not on tree) + @endverbatim +*/ +class TiXmlBase +{ + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; + +public: + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. + void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. + const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, + or they will be transformed into entities! + */ + static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; + +protected: + + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) + { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } + + #ifdef TIXML_USE_STL + static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); + static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); + #endif + + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) { + _value[i] = p[i]; + } + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; + + /// Field containing a generic user pointer + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + +private: + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; +}; + + +/** The parent class for everything in the Document Object Model. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TiXmlNode + can be queried, and it can be cast to its more defined type. +*/ +class TiXmlNode : public TiXmlBase +{ + friend class TiXmlDocument; + friend class TiXmlElement; + +public: + #ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); + + #endif + + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + TINYXML_DOCUMENT, + TINYXML_ELEMENT, + TINYXML_COMMENT, + TINYXML_UNKNOWN, + TINYXML_TEXT, + TINYXML_DECLARATION, + TINYXML_TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char *Value() const { return value.c_str (); } + + #ifdef TIXML_USE_STL + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { return value; } + #endif + + const TIXML_STRING& ValueTStr() const { return value; } + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { value = _value;} + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * _value ) { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * _value ) { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + #endif + + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + #endif + + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + + + /** Add a new node related to this. Adds a child past the LastChild. + + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. + + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char *_prev ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char* _next ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char *_next ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * _value ) const; + TiXmlElement* FirstChildElement( const char * _value ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: DOCUMENT, ELEMENT, COMMENT, + UNKNOWN, TEXT, and DECLARATION. + */ + int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + + virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + +protected: + TiXmlNode( NodeType _type ); + + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; + + #ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; + #endif + + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + TIXML_STRING value; + + TiXmlNode* prev; + TiXmlNode* next; + +private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. +}; + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not TiXmlNodes, since they are not + part of the tinyXML document object model. There are other + suggested ways to look at this problem. +*/ +class TiXmlAttribute : public TiXmlBase +{ + friend class TiXmlAttributeSet; + +public: + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + #endif + + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. + #ifdef TIXML_USE_STL + const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. + #endif + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { return name; } + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; + + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. + + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetName( const std::string& _name ) { name = _name; } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } + +private: + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; +}; + + +/* A class used to manage a group of attributes. + It is only used internally, both by the ELEMENT and the DECLARATION. + + The set can be changed transparent to the Element and Declaration + classes that use it, but NOT transparent to the Attribute + which has to implement a next() and previous() method. Which makes + it a bit problematic and prevents the use of STL. + + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. +*/ +class TiXmlAttributeSet +{ +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* FindOrCreate( const char* _name ); + +# ifdef TIXML_USE_STL + TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* FindOrCreate( const std::string& _name ); +# endif + + +private: + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + + TiXmlAttribute sentinel; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TiXmlElement : public TiXmlNode +{ +public: + /// Construct an element. + TiXmlElement (const char * in_value); + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlElement( const std::string& _value ); + #endif + + TiXmlElement( const TiXmlElement& ); + + void operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) { + *_value = (float)d; + } + return result; + } + + #ifdef TIXML_USE_STL + /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). + int QueryStringAttribute( const char* name, std::string* _value ) const { + const char* cstr = Attribute( name ); + if ( cstr ) { + *_value = std::string( cstr ); + return TIXML_SUCCESS; + } + return TIXML_NO_ATTRIBUTE; + } + + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + NOTE: This method doesn't work correctly for 'string' types that contain spaces. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + + int QueryValueAttribute( const std::string& name, std::string* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + *outValue = node->ValueStr(); + return TIXML_SUCCESS; + } + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * _value ); + + #ifdef TIXML_USE_STL + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + ///< STL std::string form. + void SetDoubleAttribute( const std::string& name, double value ); + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); + #ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + #endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well + + // Used to be public [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +private: + TiXmlAttributeSet attributeSet; +}; + + +/** An XML comment. +*/ +class TiXmlComment : public TiXmlNode +{ +public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + void operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlComment* target ) const; + + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif +// virtual void StreamOut( TIXML_OSTREAM * out ) const; + +private: + +}; + + +/** XML text. A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCDATA() and query it with CDATA(). +*/ +class TiXmlText : public TiXmlNode +{ + friend class TiXmlElement; +public: + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + #endif + + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } + void operator=( const TiXmlText& base ) { base.CopyTo( this ); } + + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { return cdata; } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { cdata = _cdata; } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; + + bool Blank() const; // returns true if all white space and new lines + // [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + bool cdata; // true if this should be input and output as a CDATA style text element +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. + + Note: In this version of the code, the attributes are + handled as special cases, not generic attributes, simply + because there can only be at most 3 and they are always the same. +*/ +class TiXmlDeclaration : public TiXmlNode +{ +public: + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); +#endif + + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + void operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; +}; + + +/** Any tag that tinyXml doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into TiXmlUnknowns. +*/ +class TiXmlUnknown : public TiXmlNode +{ +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } + void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected: + void CopyTo( TiXmlUnknown* target ) const; + + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + +}; + + +/** Always the top level node. A document binds together all the + XML pieces. It can be saved, loaded, and printed to the screen. + The 'value' of a document node is the xml file name. +*/ +class TiXmlDocument : public TiXmlNode +{ +public: + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); + #endif + + TiXmlDocument( const TiXmlDocument& copy ); + void operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; + + #ifdef TIXML_USE_STL + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. + { + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const ///< STL std::string version. + { + return SaveFile( filename.c_str() ); + } + #endif + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { return errorLocation.row+1; } + int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { Print( stdout, 0 ); } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + // [internal use] + virtual TiXmlNode* Clone() const; + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. +}; + + +/** + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); + if ( !child ) + break; + // do something + ++i; + } + @endverbatim + + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @endverbatim +*/ +class TiXmlHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + + #ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + #endif + + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { return node; } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { return ToNode(); } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { return ToElement(); } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { return ToText(); } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { return ToUnknown(); } + +private: + TiXmlNode* node; +}; + + +/** Print to memory functionality. The TiXmlPrinter is useful when you need to: + + -# Print to memory (especially in non-STL mode) + -# Control formatting (line endings, etc.) + + When constructed, the TiXmlPrinter is in its default "pretty printing" mode. + Before calling Accept() you can call methods to control the printing + of the XML document. After TiXmlNode::Accept() is called, the printed document can + be accessed via the CStr(), Str(), and Size() methods. + + TiXmlPrinter uses the Visitor API. + @verbatim + TiXmlPrinter printer; + printer.SetIndent( "\t" ); + + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + @endverbatim +*/ +class TiXmlPrinter : public TiXmlVisitor +{ +public: + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } + /// Query the indention string. + const char* Indent() { return indent.c_str(); } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } + /// Query the current line breaking string. + const char* LineBreak() { return lineBreak.c_str(); } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() { indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { return buffer.c_str(); } + /// Return the length of the result string. + size_t Size() { return buffer.size(); } + + #ifdef TIXML_USE_STL + /// Return the result. + const std::string& Str() { return buffer; } + #endif + +private: + void DoIndent() { + for( int i=0; i +#include + +#include "tinyxml.h" + +//#define DEBUG_PARSER +#if defined( DEBUG_PARSER ) +# if defined( DEBUG ) && defined( _MSC_VER ) +# include +# define TIXML_LOG OutputDebugString +# else +# define TIXML_LOG printf +# endif +#endif + +// Note tha "PutString" hardcodes the same list. This +// is less flexible than it appears. Changing the entries +// or order will break putstring. +TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = +{ + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 6, '\'' } +}; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// Including the basic of this table, which determines the #bytes in the +// sequence from the lead byte. 1 placed for invalid sequences -- +// although the result will be junk, pass it through as much as possible. +// Beware of the non-characters in UTF-8: +// ef bb bf (Microsoft "lead bytes") +// ef bf be +// ef bf bf + +const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +const int TiXmlBase::utf8ByteTable[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte + 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid +}; + + +void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) + *length = 1; + else if ( input < 0x800 ) + *length = 2; + else if ( input < 0x10000 ) + *length = 3; + else if ( input < 0x200000 ) + *length = 4; + else + { *length = 0; return; } // This code won't covert this correctly anyway. + + output += *length; + + // Scary scary fall throughs. + switch (*length) + { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + } +} + + +/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalpha( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalpha( anyByte ); +// } +} + + +/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalnum( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalnum( anyByte ); +// } +} + + +class TiXmlParsingData +{ + friend class TiXmlDocument; + public: + void Stamp( const char* now, TiXmlEncoding encoding ); + + const TiXmlCursor& Cursor() { return cursor; } + + private: + // Only used by the document! + TiXmlParsingData( const char* start, int _tabsize, int row, int col ) + { + assert( start ); + stamp = start; + tabsize = _tabsize; + cursor.row = row; + cursor.col = col; + } + + TiXmlCursor cursor; + const char* stamp; + int tabsize; +}; + + +void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) +{ + assert( now ); + + // Do nothing if the tabsize is 0. + if ( tabsize < 1 ) + { + return; + } + + // Get the current row, column. + int row = cursor.row; + int col = cursor.col; + const char* p = stamp; + assert( p ); + + while ( p < now ) + { + // Treat p as unsigned, so we have a happy compiler. + const unsigned char* pU = (const unsigned char*)p; + + // Code contributed by Fletcher Dunn: (modified by lee) + switch (*pU) { + case 0: + // We *should* never get here, but in case we do, don't + // advance past the terminating null character, ever + return; + + case '\r': + // bump down to the next line + ++row; + col = 0; + // Eat the character + ++p; + + // Check for \r\n sequence, and treat this as a single character + if (*p == '\n') { + ++p; + } + break; + + case '\n': + // bump down to the next line + ++row; + col = 0; + + // Eat the character + ++p; + + // Check for \n\r sequence, and treat this as a single + // character. (Yes, this bizarre thing does occur still + // on some arcane platforms...) + if (*p == '\r') { + ++p; + } + break; + + case '\t': + // Eat the character + ++p; + + // Skip to next tab stop + col = (col / tabsize + 1) * tabsize; + break; + + case TIXML_UTF_LEAD_0: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( *(p+1) && *(p+2) ) + { + // In these cases, don't advance the column. These are + // 0-width spaces. + if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) + p += 3; + else + { p +=3; ++col; } // A normal character. + } + } + else + { + ++p; + ++col; + } + break; + + default: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // Eat the 1 to 4 byte utf8 character. + int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; + if ( step == 0 ) + step = 1; // Error case from bad encoding, but handle gracefully. + p += step; + + // Just advance one column, of course. + ++col; + } + else + { + ++p; + ++col; + } + break; + } + } + cursor.row = row; + cursor.col = col; + assert( cursor.row >= -1 ); + assert( cursor.col >= -1 ); + stamp = p; + assert( stamp ); +} + + +const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) +{ + if ( !p || !*p ) + { + return 0; + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + while ( *p ) + { + const unsigned char* pU = (const unsigned char*)p; + + // Skip the stupid Microsoft UTF-8 Byte order marks + if ( *(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==TIXML_UTF_LEAD_1 + && *(pU+2)==TIXML_UTF_LEAD_2 ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbeU ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbfU ) + { + p += 3; + continue; + } + + if ( IsWhiteSpace( *p ) ) // Still using old rules for white space. + ++p; + else + break; + } + } + else + { + while ( *p && IsWhiteSpace( *p ) ) + ++p; + } + + return p; +} + +#ifdef TIXML_USE_STL +/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) +{ + for( ;; ) + { + if ( !in->good() ) return false; + + int c = in->peek(); + // At this scope, we can't get to a document. So fail silently. + if ( !IsWhiteSpace( c ) || c <= 0 ) + return true; + + *tag += (char) in->get(); + } +} + +/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) +{ + //assert( character > 0 && character < 128 ); // else it won't work in utf-8 + while ( in->good() ) + { + int c = in->peek(); + if ( c == character ) + return true; + if ( c <= 0 ) // Silent failure: can't get document at this scope + return false; + + in->get(); + *tag += (char) c; + } + return false; +} +#endif + +// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The +// "assign" optimization removes over 10% of the execution time. +// +const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) +{ + // Oddly, not supported on some comilers, + //name->clear(); + // So use this: + *name = ""; + assert( p ); + + // Names start with letters or underscores. + // Of course, in unicode, tinyxml has no idea what a letter *is*. The + // algorithm is generous. + // + // After that, they can be letters, underscores, numbers, + // hyphens, or colons. (Colons are valid ony for namespaces, + // but tinyxml can't tell namespaces from names.) + if ( p && *p + && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) + { + const char* start = p; + while( p && *p + && ( IsAlphaNum( (unsigned char ) *p, encoding ) + || *p == '_' + || *p == '-' + || *p == '.' + || *p == ':' ) ) + { + //(*name) += *p; // expensive + ++p; + } + if ( p-start > 0 ) { + name->assign( start, p-start ); + } + return p; + } + return 0; +} + +const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) +{ + // Presume an entity, and pull it out. + TIXML_STRING ent; + int i; + *length = 0; + + if ( *(p+1) && *(p+1) == '#' && *(p+2) ) + { + unsigned long ucs = 0; + ptrdiff_t delta = 0; + unsigned mult = 1; + + if ( *(p+2) == 'x' ) + { + // Hexadecimal. + if ( !*(p+3) ) return 0; + + const char* q = p+3; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != 'x' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else if ( *q >= 'a' && *q <= 'f' ) + ucs += mult * (*q - 'a' + 10); + else if ( *q >= 'A' && *q <= 'F' ) + ucs += mult * (*q - 'A' + 10 ); + else + return 0; + mult *= 16; + --q; + } + } + else + { + // Decimal. + if ( !*(p+2) ) return 0; + + const char* q = p+2; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != '#' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else + return 0; + mult *= 10; + --q; + } + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + } + else + { + *value = (char)ucs; + *length = 1; + } + return p + delta + 1; + } + + // Now try to match it. + for( i=0; iappend( cArr, len ); + } + } + else + { + bool whitespace = false; + + // Remove leading white space: + p = SkipWhiteSpace( p, encoding ); + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) ) + { + if ( *p == '\r' || *p == '\n' ) + { + whitespace = true; + ++p; + } + else if ( IsWhiteSpace( *p ) ) + { + whitespace = true; + ++p; + } + else + { + // If we've found whitespace, add it before the + // new character. Any whitespace just becomes a space. + if ( whitespace ) + { + (*text) += ' '; + whitespace = false; + } + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + if ( len == 1 ) + (*text) += cArr[0]; // more efficient + else + text->append( cArr, len ); + } + } + } + if ( p && *p ) + p += strlen( endTag ); + return p; +} + +#ifdef TIXML_USE_STL + +void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + // The basic issue with a document is that we don't know what we're + // streaming. Read something presumed to be a tag (and hope), then + // identify it, and call the appropriate stream method on the tag. + // + // This "pre-streaming" will never read the closing ">" so the + // sub-tag can orient itself. + + if ( !StreamTo( in, '<', tag ) ) + { + SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + while ( in->good() ) + { + int tagIndex = (int) tag->length(); + while ( in->good() && in->peek() != '>' ) + { + int c = in->get(); + if ( c <= 0 ) + { + SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + break; + } + (*tag) += (char) c; + } + + if ( in->good() ) + { + // We now have something we presume to be a node of + // some sort. Identify it, and call the node to + // continue streaming. + TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); + + if ( node ) + { + node->StreamIn( in, tag ); + bool isElement = node->ToElement() != 0; + delete node; + node = 0; + + // If this is the root element, we're done. Parsing will be + // done by the >> operator. + if ( isElement ) + { + return; + } + } + else + { + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + } + } + // We should have returned sooner. + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); +} + +#endif + +const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) +{ + ClearError(); + + // Parse away, at the document level. Since a document + // contains nothing but other tags, most of what happens + // here is skipping white space. + if ( !p || !*p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + // Note that, for a document, this needs to come + // before the while space skip, so that parsing + // starts from the pointer we are given. + location.Clear(); + if ( prevData ) + { + location.row = prevData->cursor.row; + location.col = prevData->cursor.col; + } + else + { + location.row = 0; + location.col = 0; + } + TiXmlParsingData data( p, TabSize(), location.row, location.col ); + location = data.Cursor(); + + if ( encoding == TIXML_ENCODING_UNKNOWN ) + { + // Check for the Microsoft UTF-8 lead bytes. + const unsigned char* pU = (const unsigned char*)p; + if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 + && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 + && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) + { + encoding = TIXML_ENCODING_UTF8; + useMicrosoftBOM = true; + } + } + + p = SkipWhiteSpace( p, encoding ); + if ( !p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + while ( p && *p ) + { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) + { + p = node->Parse( p, &data, encoding ); + LinkEndChild( node ); + } + else + { + break; + } + + // Did we get encoding info? + if ( encoding == TIXML_ENCODING_UNKNOWN + && node->ToDeclaration() ) + { + TiXmlDeclaration* dec = node->ToDeclaration(); + const char* enc = dec->Encoding(); + assert( enc ); + + if ( *enc == 0 ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice + else + encoding = TIXML_ENCODING_LEGACY; + } + + p = SkipWhiteSpace( p, encoding ); + } + + // Was this empty? + if ( !firstChild ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); + return 0; + } + + // All is well. + return p; +} + +void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + // The first error in a chain is more accurate - don't set again! + if ( error ) + return; + + assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); + error = true; + errorId = err; + errorDesc = errorString[ errorId ]; + + errorLocation.Clear(); + if ( pError && data ) + { + data->Stamp( pError, encoding ); + errorLocation = data->Cursor(); + } +} + + +TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) +{ + TiXmlNode* returnNode = 0; + + p = SkipWhiteSpace( p, encoding ); + if( !p || !*p || *p != '<' ) + { + return 0; + } + + p = SkipWhiteSpace( p, encoding ); + + if ( !p || !*p ) + { + return 0; + } + + // What is this thing? + // - Elements start with a letter or underscore, but xml is reserved. + // - Comments: "; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // [ 1475201 ] TinyXML parses entities in comments + // Oops - ReadText doesn't work, because we don't want to parse the entities. + // p = ReadText( p, &value, false, endTag, false, encoding ); + // + // from the XML spec: + /* + [Definition: Comments may appear anywhere in a document outside other markup; in addition, + they may appear within the document type declaration at places allowed by the grammar. + They are not part of the document's character data; an XML processor MAY, but need not, + make it possible for an application to retrieve the text of comments. For compatibility, + the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity + references MUST NOT be recognized within comments. + + An example of a comment: + + + */ + + value = ""; + // Keep all the white space. + while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) + { + value.append( p, 1 ); + ++p; + } + if ( p && *p ) + p += strlen( endTag ); + + return p; +} + + +const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) return 0; + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + // Read the name, the '=' and the value. + const char* pErr = p; + p = ReadName( p, &name, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p || *p != '=' ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + ++p; // skip '=' + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + const char* end; + const char SINGLE_QUOTE = '\''; + const char DOUBLE_QUOTE = '\"'; + + if ( *p == SINGLE_QUOTE ) + { + ++p; + end = "\'"; // single quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else if ( *p == DOUBLE_QUOTE ) + { + ++p; + end = "\""; // double quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else + { + // All attribute values should be in single or double quotes. + // But this is such a common error that the parser will try + // its best, even without them. + value = ""; + while ( p && *p // existence + && !IsWhiteSpace( *p ) // whitespace + && *p != '/' && *p != '>' ) // tag end + { + if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { + // [ 1451649 ] Attribute values with trailing quotes not handled correctly + // We did not have an opening quote but seem to have a + // closing one. Give up and throw an error. + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + value += *p; + ++p; + } + } + return p; +} + +#ifdef TIXML_USE_STL +void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->peek(); + if ( !cdata && (c == '<' ) ) + { + return; + } + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + in->get(); // "commits" the peek made above + + if ( cdata && c == '>' && tag->size() >= 3 ) { + size_t len = tag->size(); + if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { + // terminator of cdata. + return; + } + } + } +} +#endif + +const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + value = ""; + TiXmlDocument* document = GetDocument(); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + const char* const startTag = ""; + + if ( cdata || StringEqual( p, startTag, false, encoding ) ) + { + cdata = true; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // Keep all the white space, ignore the encoding, etc. + while ( p && *p + && !StringEqual( p, endTag, false, encoding ) + ) + { + value += *p; + ++p; + } + + TIXML_STRING dummy; + p = ReadText( p, &dummy, false, endTag, false, encoding ); + return p; + } + else + { + bool ignoreWhite = true; + + const char* end = "<"; + p = ReadText( p, &value, ignoreWhite, end, false, encoding ); + if ( p ) + return p-1; // don't truncate the '<' + return 0; + } +} + +#ifdef TIXML_USE_STL +void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) + { + // All is well. + return; + } + } +} +#endif + +const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) +{ + p = SkipWhiteSpace( p, _encoding ); + // Find the beginning, find the end, and look for + // the stuff in-between. + TiXmlDocument* document = GetDocument(); + if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); + return 0; + } + if ( data ) + { + data->Stamp( p, _encoding ); + location = data->Cursor(); + } + p += 5; + + version = ""; + encoding = ""; + standalone = ""; + + while ( p && *p ) + { + if ( *p == '>' ) + { + ++p; + return p; + } + + p = SkipWhiteSpace( p, _encoding ); + if ( StringEqual( p, "version", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + version = attrib.Value(); + } + else if ( StringEqual( p, "encoding", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + encoding = attrib.Value(); + } + else if ( StringEqual( p, "standalone", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + standalone = attrib.Value(); + } + else + { + // Read over whatever it is. + while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) + ++p; + } + } + return 0; +} + +bool TiXmlText::Blank() const +{ + for ( unsigned i=0; i +// ---------------------------------- + + +#include "stdafx.h" +#include "tier0/platform.h" +#include +#include +#include +#include + +#include "vcprojconvert.h" +#include "utlvector.h" + +//----------------------------------------------------------------------------- +// Purpose: constructor +//----------------------------------------------------------------------------- +CVCProjConvert::CVCProjConvert() +{ + m_bProjectLoaded = false; + m_bIs2010 = false; +} + +//----------------------------------------------------------------------------- +// Purpose: destructor +//----------------------------------------------------------------------------- +CVCProjConvert::~CVCProjConvert() +{ + +} + +//----------------------------------------------------------------------------- +// Purpose: load up a project and parse it +//----------------------------------------------------------------------------- +bool CVCProjConvert::LoadProject( const char *project ) +{ + TiXmlDocument doc( project ); + if ( !doc.LoadFile() ) + return false; + + // VC2010 Update + if ( Q_strstr( project, ".vcxproj" ) ) + m_bIs2010 = true; + + TiXmlNode *pStart; + if ( m_bIs2010 ) + pStart = doc.FirstChild("Project"); + else + pStart = doc.FirstChild("VisualStudioProject"); + + if ( !pStart ) + return false; + + TiXmlHandle docHandle(pStart); + + ExtractProjectName( docHandle ); + if ( !m_Name.IsValid() ) + { + Msg( "Failed to extract project name\n" ); + return false; + } + char baseDir[ MAX_PATH ]; + Q_ExtractFilePath( project, baseDir, sizeof(baseDir) ); + Q_StripTrailingSlash( baseDir ); + m_BaseDir = baseDir; + + ExtractConfigurations( docHandle ); + if ( m_Configurations.Count() == 0 ) + { + Msg( "Failed to find any configurations to load\n" ); + return false; + } + + ExtractFiles( docHandle ); + + m_bProjectLoaded = true; + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: returns the number of different configurations loaded +//----------------------------------------------------------------------------- +int CVCProjConvert::GetNumConfigurations() +{ + Assert( m_bProjectLoaded ); + return m_Configurations.Count(); + +} + +//----------------------------------------------------------------------------- +// Purpose: returns the index of a config with this name, -1 on err +//----------------------------------------------------------------------------- +int CVCProjConvert::FindConfiguration( CUtlSymbol name ) +{ + if ( !name.IsValid() ) + { + return -1; + } + + for ( int i = 0; i < m_Configurations.Count(); i++ ) + { + if ( m_Configurations[i].GetName() == name ) + { + return i; + } + } + return -1; +} + +//----------------------------------------------------------------------------- +// Purpose: returns the config object at this index +//----------------------------------------------------------------------------- +CVCProjConvert::CConfiguration & CVCProjConvert::GetConfiguration( int i ) +{ + Assert( m_bProjectLoaded ); + Assert( m_Configurations.IsValidIndex(i) ); + return m_Configurations[i]; +} + +//----------------------------------------------------------------------------- +// Purpose: extracts the project name from the loaded vcproj +//----------------------------------------------------------------------------- +bool CVCProjConvert::ExtractProjectName( TiXmlHandle &hDoc ) +{ + if ( m_bIs2010 ) + { + TiXmlElement *pProp = hDoc.FirstChild("PropertyGroup").ToElement(); + for ( pProp; pProp; pProp = pProp->NextSiblingElement() ) + { + TiXmlNode *pName = pProp->FirstChild("ProjectName"); + if ( pName ) + { + m_Name = pName->ToElement()->GetText(); + return true; + } + } + } + else + { + m_Name = hDoc.Element()->Attribute("Name"); + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: extracts the list of configuration names from the vcproj +//----------------------------------------------------------------------------- +bool CVCProjConvert::ExtractConfigurations( TiXmlHandle &hDoc ) +{ + m_Configurations.RemoveAll(); + + if ( m_bIs2010 ) + { + TiXmlElement *pItemGroup = hDoc.FirstChild( "ItemGroup" ).ToElement(); + for ( pItemGroup; pItemGroup; pItemGroup = pItemGroup->NextSiblingElement() ) + { + const char *label = pItemGroup->Attribute("Label"); + + if ( label && !Q_stricmp( label, "ProjectConfigurations" ) ) + { + TiXmlNode *pConfig = pItemGroup->FirstChild("ProjectConfiguration"); + for ( pConfig; pConfig; pConfig = pConfig->NextSiblingElement() ) + { + int newIndex = m_Configurations.AddToTail(); + CConfiguration & config = m_Configurations[newIndex]; + config.SetName( pConfig->ToElement()->Attribute("Include") ); + ExtractIncludes( hDoc, config ); + } + + return true; + } + } + } + else + { + TiXmlElement *pConfig = hDoc.FirstChild("Configurations").FirstChild("Configuration").ToElement(); + for ( pConfig; pConfig; pConfig = pConfig->NextSiblingElement() ) + { + int newIndex = m_Configurations.AddToTail(); + CConfiguration & config = m_Configurations[newIndex]; + config.SetName( pConfig->Attribute("Name") ); + TiXmlHandle hConfig( pConfig ); + ExtractIncludes( hConfig, config ); + } + + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: extracts the list of defines and includes used for this config +//----------------------------------------------------------------------------- +bool CVCProjConvert::ExtractIncludes( TiXmlHandle &hDoc, CConfiguration & config ) +{ + config.ResetDefines(); + config.ResetIncludes(); + + if ( m_bIs2010 ) + { + TiXmlElement *pDefGroup = hDoc.FirstChild("ItemDefinitionGroup").ToElement(); + for ( pDefGroup; pDefGroup; pDefGroup = pDefGroup->NextSiblingElement() ) + { + const char *cond = pDefGroup->Attribute("Condition"); + if ( cond && Q_stristr( cond, config.GetName().String() ) ) + break; + } + + if ( !pDefGroup ) + return false; + + TiXmlNode *pCompile = pDefGroup->FirstChild("ClCompile"); + for ( pCompile; pCompile; pCompile = pCompile->ToElement()->NextSiblingElement() ) + { + TiXmlNode *pPrePro = pCompile->FirstChild("PreprocessorDefinitions"); + TiXmlNode *pAddInc = pCompile->FirstChild("AdditionalIncludeDirectories"); + if ( pPrePro && pAddInc ) + { + CUtlSymbol defines = pPrePro->ToElement()->GetText(); + char *str = (char *)_alloca( Q_strlen( defines.String() ) + 1 ); + Q_strcpy( str, defines.String() ); + // Expanded tokenize with , or ; both are accepted by VS + char *delim = NULL; + char *try1 = strchr( str, ';' ); + char *try2 = strchr( str, ',' ); + char *curpos = str; + while ( try1 || try2 ) + { + delim = ( (try1 && !try2) || (try1 && try2 && try1 < try2) ) ? try1 : try2; + *delim = 0; + delim++; + if ( Q_stricmp( curpos, "WIN32" ) && Q_stricmp( curpos, "_WIN32" ) && + Q_stricmp( curpos, "_WINDOWS") && Q_stricmp( curpos, "WINDOWS") && + curpos[0] != '%' ) // don't add WIN32 defines + { + config.AddDefine( curpos ); + } + curpos = delim; + try1 = strchr( delim, ';' ); + try2 = strchr( delim, ',' ); + } + if ( Q_stricmp( curpos, "WIN32" ) && Q_stricmp( curpos, "_WIN32" ) && + Q_stricmp( curpos, "_WINDOWS") && Q_stricmp( curpos, "WINDOWS") && + curpos[0] != '%' ) // don't add WIN32 defines + { + config.AddDefine( curpos ); + } + + CUtlSymbol includes = pAddInc->ToElement()->GetText(); + char *str2 = (char *)_alloca( Q_strlen( includes.String() ) + 1 ); + Assert( str2 ); + Q_strcpy( str2, includes.String() ); + // Expanded tokenize with , or ; both are accepted by VS + delim = NULL; + try1 = strchr( str2, ';' ); + try2 = strchr( str2, ',' ); + curpos = str2; + while ( try1 || try2 ) + { + delim = ( (try1 && !try2) || (try1 && try2 && try1 < try2) ) ? try1 : try2; + *delim = 0; + delim++; + if ( curpos[0] != '%' ) + { + Q_FixSlashes( curpos ); + char fullPath[ MAX_PATH ]; + Q_snprintf( fullPath, sizeof(fullPath), "%s/%s", m_BaseDir.String(), curpos ); + Q_StripTrailingSlash( fullPath ); + config.AddInclude( fullPath ); + } + + curpos = delim; + try1 = strchr( delim, ';' ); + try2 = strchr( delim, ',' ); + } + + if ( curpos[0] != '%' ) + { + Q_FixSlashes( curpos ); + char fullPath[ MAX_PATH ]; + Q_snprintf( fullPath, sizeof(fullPath), "%s/%s", m_BaseDir.String(), curpos ); + Q_StripTrailingSlash( fullPath ); + config.AddInclude( fullPath ); + } + + return true; + } + } + } + else + { + // We are passed a handle to the current config to make things easy + TiXmlElement *pTool = hDoc.FirstChild("Tool").ToElement(); + for ( pTool; pTool; pTool = pTool->NextSiblingElement() ) + { + if ( !Q_stricmp( pTool->Attribute("Name"), "VCCLCompilerTool" ) ) + { + CUtlSymbol defines = pTool->Attribute("PreprocessorDefinitions"); + char *str = (char *)_alloca( Q_strlen( defines.String() ) + 1 ); + Q_strcpy( str, defines.String() ); + // Expanded tokenize with , or ; both are accepted by VS + char *delim = NULL; + char *try1 = strchr( str, ';' ); + char *try2 = strchr( str, ',' ); + char *curpos = str; + while ( try1 || try2 ) + { + delim = ( (try1 && !try2) || (try1 && try2 && try1 < try2) ) ? try1 : try2; + *delim = 0; + delim++; + if ( Q_stricmp( curpos, "WIN32" ) && Q_stricmp( curpos, "_WIN32" ) && + Q_stricmp( curpos, "_WINDOWS") && Q_stricmp( curpos, "WINDOWS") ) // don't add WIN32 defines + { + config.AddDefine( curpos ); + } + + curpos = delim; + try1 = strchr( delim, ';' ); + try2 = strchr( delim, ',' ); + } + if ( Q_stricmp( curpos, "WIN32" ) && Q_stricmp( curpos, "_WIN32" ) && + Q_stricmp( curpos, "_WINDOWS") && Q_stricmp( curpos, "WINDOWS") ) // don't add WIN32 defines + { + config.AddDefine( curpos ); + } + + CUtlSymbol includes = pTool->Attribute("AdditionalIncludeDirectories"); + char *str2 = (char *)_alloca( Q_strlen( includes.String() ) + 1 ); + Assert( str2 ); + Q_strcpy( str2, includes.String() ); + // Expanded tokenize with , or ; both are accepted by VS + delim = NULL; + try1 = strchr( str2, ';' ); + try2 = strchr( str2, ',' ); + curpos = str2; + while ( try1 || try2 ) + { + delim = ( (try1 && !try2) || (try1 && try2 && try1 < try2) ) ? try1 : try2; + *delim = 0; + delim++; + Q_FixSlashes( curpos ); + char fullPath[ MAX_PATH ]; + Q_snprintf( fullPath, sizeof(fullPath), "%s/%s", m_BaseDir.String(), curpos ); + Q_StripTrailingSlash( fullPath ); + config.AddInclude( fullPath ); + + curpos = delim; + try1 = strchr( delim, ';' ); + try2 = strchr( delim, ',' ); + } + + Q_FixSlashes( curpos ); + char fullPath[ MAX_PATH ]; + Q_snprintf( fullPath, sizeof(fullPath), "%s/%s", m_BaseDir.String(), curpos ); + Q_StripTrailingSlash( fullPath ); + config.AddInclude( fullPath ); + return true; + } + } // End Tool loop + } // End m_bIs2010 + + return true; +} + +void CVCProjConvert::RecursivelyAddFiles( TiXmlElement * pFilter, TiXmlHandle & hDoc ) +{ + for ( pFilter; pFilter; pFilter = pFilter->NextSiblingElement() ) + { + TiXmlNode * pChildFilter = pFilter->FirstChild("Filter"); + + if ( pChildFilter ) + { + RecursivelyAddFiles(pChildFilter->ToElement(), hDoc); + } + + TiXmlNode *pFile = pFilter->FirstChild("File"); + for ( pFile; pFile; pFile = pFile->NextSibling() ) + { + CUtlSymbol fileName = pFile->ToElement()->Attribute("RelativePath"); + if ( fileName.IsValid() ) + { + char fixedFileName[ MAX_PATH ]; + Q_strncpy( fixedFileName, fileName.String(), sizeof(fixedFileName) ); + printf( fixedFileName ); + printf( "\n" ); + if ( fixedFileName[0] == '.' && fixedFileName[1] == '\\' ) + { + Q_memmove( fixedFileName, fixedFileName+2, sizeof(fixedFileName)-2 ); + } + + Q_FixSlashes( fixedFileName ); + FindFileCaseInsensitive( fixedFileName, sizeof(fixedFileName) ); + + TiXmlNode *pExclude = pFile->FirstChild("FileConfiguration"); + const char *pExcluded = pExclude ? pExclude->ToElement()->Attribute("ExcludedFromBuild") : NULL; + CConfiguration::FileType_e type = GetFileType( fileName.String() ); + CConfiguration::CFileEntry fileEntry( fixedFileName, type ); + for ( int i = 0; i < m_Configurations.Count(); i++ ) // add the file to all configs + { + CConfiguration & config = m_Configurations[i]; + // Don't add this file if it is excluded from this config's build + if ( pExclude && pExcluded && Q_stristr(pExclude->ToElement()->Attribute("Name"), config.GetName().String()) && Q_stricmp(pExcluded, "true") ) + continue; + + config.InsertFile( fileEntry ); + } + } + } // file for + } //filter for +} + +//----------------------------------------------------------------------------- +// Purpose: walks the file elements in the vcproj and inserts them into configs +//----------------------------------------------------------------------------- +bool CVCProjConvert::ExtractFiles( TiXmlHandle &hDoc ) +{ + Assert( m_Configurations.Count() ); // some configs must be loaded first + + if ( m_bIs2010 ) + { + // *.vcxproj + // + // + // + // + // + // + + // Get ClCompile files + TiXmlElement *pDefGroup = hDoc.FirstChild("ItemGroup").ToElement(); + for ( pDefGroup; pDefGroup; pDefGroup = pDefGroup->NextSiblingElement() ) + { + if ( pDefGroup->FirstChild("ClCompile") && pDefGroup->FirstChild("ClCompile")->ToElement()->Attribute("Include") ) + break; + } + + if ( !pDefGroup ) + return false; + + TiXmlNode *pFile = pDefGroup->FirstChild( "ClCompile" ); + for ( pFile; pFile; pFile = pFile->NextSibling() ) + { + CUtlSymbol fileName = pFile->ToElement()->Attribute("Include"); + if ( fileName.IsValid() ) + { + char fixedFileName[ MAX_PATH ]; + Q_strncpy( fixedFileName, fileName.String(), sizeof(fixedFileName) ); + if ( fixedFileName[0] == '.' && fixedFileName[1] == '\\' ) + { + Q_memmove( fixedFileName, fixedFileName+2, sizeof(fixedFileName)-2 ); + } + + Q_FixSlashes( fixedFileName ); + FindFileCaseInsensitive( fixedFileName, sizeof(fixedFileName) ); + + TiXmlNode *pExclude = pFile->FirstChild("ExcludedFromBuild"); + CConfiguration::FileType_e type = GetFileType( fileName.String() ); + CConfiguration::CFileEntry fileEntry( fixedFileName, type ); + for ( int i = 0; i < m_Configurations.Count(); i++ ) // add the file to all configs + { + CConfiguration & config = m_Configurations[i]; + // Don't add this file if it is excluded from this config's build + if ( pExclude && Q_stricmp( pExclude->ToElement()->GetText(), "true" ) && Q_stristr( pExclude->ToElement()->Attribute("Condition"), config.GetName().String() ) ) + continue; + + config.InsertFile( fileEntry ); + } + } + } + + + // Get ClInclude files + pDefGroup = hDoc.FirstChild("ItemGroup").ToElement(); + for ( pDefGroup; pDefGroup; pDefGroup = pDefGroup->NextSiblingElement() ) + { + if ( pDefGroup->FirstChild("ClInclude") && pDefGroup->FirstChild("ClInclude")->ToElement()->Attribute("Include") ) + break; + } + + if ( !pDefGroup ) + return false; + + pFile = pDefGroup->FirstChild( "ClInclude" ); + for ( pFile; pFile; pFile = pFile->NextSibling() ) + { + CUtlSymbol fileName = pFile->ToElement()->Attribute("Include"); + if ( fileName.IsValid() ) + { + char fixedFileName[ MAX_PATH ]; + Q_strncpy( fixedFileName, fileName.String(), sizeof(fixedFileName) ); + if ( fixedFileName[0] == '.' && fixedFileName[1] == '\\' ) + { + Q_memmove( fixedFileName, fixedFileName+2, sizeof(fixedFileName)-2 ); + } + + Q_FixSlashes( fixedFileName ); + FindFileCaseInsensitive( fixedFileName, sizeof(fixedFileName) ); + + TiXmlNode *pExclude = pFile->FirstChild("ExcludedFromBuild"); + CConfiguration::FileType_e type = GetFileType( fileName.String() ); + CConfiguration::CFileEntry fileEntry( fixedFileName, type ); + for ( int i = 0; i < m_Configurations.Count(); i++ ) // add the file to all configs + { + CConfiguration & config = m_Configurations[i]; + // Don't add this file if it is excluded from this config's build + if ( pExclude && Q_stricmp( pExclude->ToElement()->GetText(), "true" ) && Q_stristr( pExclude->ToElement()->Attribute("Condition"), config.GetName().String() ) ) + continue; + + config.InsertFile( fileEntry ); + } + } + } + } + else + { + TiXmlElement *pFilter = hDoc.FirstChild("Files").FirstChild("Filter").ToElement(); + + RecursivelyAddFiles( pFilter, hDoc ); + } + + return true; +} + + + +#ifdef _LINUX +static char fileName[MAX_PATH]; +int CheckName(const struct dirent *dir) +{ + return !strcasecmp( dir->d_name, fileName ); +} + +const char *findFileInDirCaseInsensitive(const char *file) +{ + const char *dirSep = strrchr(file,'/'); + if( !dirSep ) + { + dirSep=strrchr(file,'\\'); + if( !dirSep ) + { + return NULL; + } + } + + char *dirName = static_cast( alloca( ( dirSep - file ) +1 ) ); + if( !dirName ) + return NULL; + + Q_strncpy( dirName, file, dirSep - file ); + dirName[ dirSep - file ] = '\0'; + + struct dirent **namelist; + int n; + + Q_strncpy( fileName, dirSep + 1, MAX_PATH ); + + + n = scandir( dirName , &namelist, CheckName, alphasort ); + + if( n > 0 ) + { + while( n > 1 ) + { + free( namelist[n] ); // free the malloc'd strings + n--; + } + + Q_snprintf( fileName, sizeof( fileName ), "%s/%s", dirName, namelist[0]->d_name ); + return fileName; + } + else + { + // last ditch attempt, just return the lower case version! + Q_strncpy( fileName, file, sizeof(fileName) ); + Q_strlower( fileName ); + return fileName; + } +} +#endif + +void CVCProjConvert::FindFileCaseInsensitive( char *fileName, int fileNameSize ) +{ + char filePath[ MAX_PATH ]; + + Q_snprintf( filePath, sizeof(filePath), "%s/%s", m_BaseDir.String(), fileName ); + + struct _stat buf; + if ( _stat( filePath, &buf ) == 0) + { + return; // found the filename directly + } + +#ifdef _LINUX + const char *realName = findFileInDirCaseInsensitive( filePath ); + if ( realName ) + { + Q_strncpy( fileName, realName+strlen(m_BaseDir.String())+1, fileNameSize ); + } +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: extracts the generic type of a file being loaded +//----------------------------------------------------------------------------- +CVCProjConvert::CConfiguration::FileType_e CVCProjConvert::GetFileType( const char *fileName ) +{ + CConfiguration::FileType_e type = CConfiguration::FILE_TYPE_UNKNOWN_E; + char ext[10]; + Q_ExtractFileExtension( fileName, ext, sizeof(ext) ); + if ( !Q_stricmp( ext, "lib" ) ) + { + type = CConfiguration::FILE_LIBRARY; + } + else if ( !Q_stricmp( ext, "h" ) ) + { + type = CConfiguration::FILE_HEADER; + } + else if ( !Q_stricmp( ext, "hh" ) ) + { + type = CConfiguration::FILE_HEADER; + } + else if ( !Q_stricmp( ext, "hpp" ) ) + { + type = CConfiguration::FILE_HEADER; + } + else if ( !Q_stricmp( ext, "cpp" ) ) + { + type = CConfiguration::FILE_SOURCE; + } + else if ( !Q_stricmp( ext, "c" ) ) + { + type = CConfiguration::FILE_SOURCE; + } + else if ( !Q_stricmp( ext, "cc" ) ) + { + type = CConfiguration::FILE_SOURCE; + } + + return type; +} diff --git a/utils/vprojtomake/vcprojconvert.h b/utils/vprojtomake/vcprojconvert.h new file mode 100644 index 00000000..dd2af90a --- /dev/null +++ b/utils/vprojtomake/vcprojconvert.h @@ -0,0 +1,118 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#ifndef VCPROJCONVERT_H +#define VCPROJCONVERT_H +#ifdef _WIN32 +#pragma once +#endif + +#include "stdafx.h" +#include "utlvector.h" +#include "utlsymbol.h" + +#ifdef _LINUX +#include "dirent.h" +#include +#define _stat stat +#endif + +#include "tinyxml/tinyxml.h" + +//----------------------------------------------------------------------------- +// Purpose: constructor +//----------------------------------------------------------------------------- +class CVCProjConvert +{ +public: + CVCProjConvert(); + ~CVCProjConvert(); + + bool LoadProject( const char *project ); + int GetNumConfigurations(); + CUtlSymbol & GetName() { return m_Name; } + CUtlSymbol & GetBaseDir() { return m_BaseDir; } + + class CConfiguration + { + public: + CConfiguration() {} + ~CConfiguration() {} + + typedef enum + { + FILE_SOURCE, + FILE_HEADER, + FILE_LIBRARY, + FILE_TYPE_UNKNOWN_E + } FileType_e; + + class CFileEntry + { + public: + CFileEntry( CUtlSymbol name, FileType_e type ) { m_Name = name; m_Type = type; } + ~CFileEntry() {} + + const char *GetName() { return m_Name.String(); } + FileType_e GetType() { return m_Type; } + bool operator==( const CFileEntry other ) const { return m_Name == other.m_Name; } + + private: + FileType_e m_Type; + CUtlSymbol m_Name; + }; + + void InsertFile( CFileEntry file ) { m_Files.AddToTail( file ); } + void RemoveFile( CUtlSymbol file ) { m_Files.FindAndRemove( CFileEntry( file, FILE_TYPE_UNKNOWN_E ) ); } // file type doesn't matter on remove + void SetName( CUtlSymbol name ) { m_Name = name; } + + int GetNumFileNames() { return m_Files.Count(); } + const char * GetFileName(int i) { return m_Files[i].GetName(); } + FileType_e GetFileType(int i) { return m_Files[i].GetType(); } + CUtlSymbol & GetName() { return m_Name; } + + void ResetDefines() { m_Defines.RemoveAll(); } + void AddDefine( CUtlSymbol define ) { m_Defines.AddToTail( define ); } + int GetNumDefines() { return m_Defines.Count(); } + const char *GetDefine( int i ) { return m_Defines[i].String(); } + + void ResetIncludes() { m_Includes.RemoveAll(); } + void AddInclude( CUtlSymbol include ) { m_Includes.AddToTail( include ); } + int GetNumIncludes() { return m_Includes.Count(); } + const char *GetInclude( int i ) { return m_Includes[i].String(); } + + private: + CUtlSymbol m_Name; + CUtlVector m_Defines; + CUtlVector m_Includes; + CUtlVector m_Files; + }; + + CConfiguration & GetConfiguration( int i ); + int FindConfiguration( CUtlSymbol name ); + +private: + bool ExtractFiles( TiXmlHandle &hDoc ); + bool ExtractConfigurations( TiXmlHandle &hDoc ); + bool ExtractProjectName( TiXmlHandle &hDoc ); + bool ExtractIncludes( TiXmlHandle &hDoc, CConfiguration & config ); + void RecursivelyAddFiles( TiXmlElement * pFilter, TiXmlHandle & hDoc ); + + // helper funcs + CConfiguration::FileType_e GetFileType( const char *fileName ); + void FindFileCaseInsensitive( char *file, int fileNameSize ); + + // data + CUtlVector m_Configurations; + CUtlSymbol m_Name; + CUtlSymbol m_BaseDir; + bool m_bProjectLoaded; + + // VC2010 Update + bool m_bIs2010; +}; + +#endif // VCPROJCONVERT_H diff --git a/utils/vprojtomake/vprojtomake.cpp b/utils/vprojtomake/vprojtomake.cpp new file mode 100644 index 00000000..62bdf047 --- /dev/null +++ b/utils/vprojtomake/vprojtomake.cpp @@ -0,0 +1,136 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "stdafx.h" +#include +#ifdef _WIN32 +#include +#elif _LINUX +#define stricmp strcasecmp +#endif +#include "tier1/strtools.h" +#include "tier0/dbg.h" +#include "KeyValues.h" +#include "cmdlib.h" +#include "tier0/icommandline.h" +#include "vcprojconvert.h" +#include "makefilecreator.h" + +SpewRetval_t SpewFunc( SpewType_t type, char const *pMsg ) +{ + printf( "%s", pMsg ); +#ifdef _WIN32 + OutputDebugString( pMsg ); +#endif + + if ( type == SPEW_ERROR ) + { + printf( "\n" ); +#ifdef _WIN32 + OutputDebugString( "\n" ); +#endif + } + else if (type == SPEW_ASSERT) + { + return SPEW_DEBUGGER; + } + + return SPEW_CONTINUE; +} + +class MyFileSystem : public IBaseFileSystem +{ +public: + int Read( void* pOutput, int size, FileHandle_t file ) { return fread( pOutput, 1, size, (FILE *)file); } + int Write( void const* pInput, int size, FileHandle_t file ) { return fwrite( pInput, 1, size, (FILE *)file); } + FileHandle_t Open( const char *pFileName, const char *pOptions, const char *pathID = 0 ) { return (FileHandle_t)fopen( pFileName, pOptions); } + void Close( FileHandle_t file ) { fclose( (FILE *)file ); } + void Seek( FileHandle_t file, int pos, FileSystemSeek_t seekType ) {} + unsigned int Tell( FileHandle_t file ) { return 0;} + unsigned int Size( FileHandle_t file ) { return 0;} + unsigned int Size( const char *pFileName, const char *pPathID = 0 ) { return 0; } + void Flush( FileHandle_t file ) { fflush((FILE *)file); } + bool Precache( const char *pFileName, const char *pPathID = 0 ) {return false;} + bool FileExists( const char *pFileName, const char *pPathID = 0 ) {return false;} + bool IsFileWritable( char const *pFileName, const char *pPathID = 0 ) {return false;} + bool SetFileWritable( char const *pFileName, bool writable, const char *pPathID = 0 ) {return false;} + long GetFileTime( const char *pFileName, const char *pPathID = 0 ) { return 0; } + bool ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) {return false;} + bool WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf ) {return false;} + bool UnzipFile( const char *,const char *,const char * ) {return false;} +}; + +MyFileSystem g_MyFS; +IBaseFileSystem *g_pFileSystem = &g_MyFS; + +//----------------------------------------------------------------------------- +// Purpose: help text +//----------------------------------------------------------------------------- +void printusage( void ) +{ + Msg( "usage: vcprojtomake \n" ); +} + +//----------------------------------------------------------------------------- +// Purpose: debug helper, spits out a human readable keyvalues version of the various configs +//----------------------------------------------------------------------------- +void OutputKeyValuesVersion( CVCProjConvert & proj ) +{ + KeyValues *kv = new KeyValues( "project" ); + for ( int projIndex = 0; projIndex < proj.GetNumConfigurations(); projIndex++ ) + { + CVCProjConvert::CConfiguration & config = proj.GetConfiguration(projIndex); + KeyValues *configKv = kv->FindKey( config.GetName().String(), true ); + int fileCount = 0; + for( int fileIndex = 0; fileIndex < config.GetNumFileNames(); fileIndex++ ) + { + if ( config.GetFileType(fileIndex) == CVCProjConvert::CConfiguration::FILE_SOURCE ) + { + char num[20]; + Q_snprintf( num, sizeof(num), "%i", fileCount ); + fileCount++; + configKv->SetString( num, config.GetFileName(fileIndex) ); + } + } + } + kv->SaveToFile( g_pFileSystem, "files.vdf" ); + kv->deleteThis(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : argc - +// argv[] - +// Output : int +//----------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + SpewOutputFunc( SpewFunc ); + + Msg( "Valve Software - vcprojtomake.exe (%s)\n", __DATE__ ); + Msg( "Modified for VS2010 Support by Killer Monkey\n" ); + Msg( "\n" ); + CommandLine()->CreateCmdLine( argc, argv ); + + if ( CommandLine()->ParmCount() < 2) + { + printusage(); + return 0; + } + + CVCProjConvert proj; + if ( !proj.LoadProject( CommandLine()->GetParm( 1 )) ) + { + Msg( "Failed to parse project\n" ); + return -1; + } + + OutputKeyValuesVersion(proj); + + CMakefileCreator makefile; + makefile.CreateMakefiles( proj ); + return 0; +} diff --git a/utils/vprojtomake/vprojtomake.sln b/utils/vprojtomake/vprojtomake.sln new file mode 100644 index 00000000..906da2c1 --- /dev/null +++ b/utils/vprojtomake/vprojtomake.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vprojtomake", "vprojtomake.vcxproj", "{EA55446E-BC04-491C-A9F0-605DFCBB213A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EA55446E-BC04-491C-A9F0-605DFCBB213A}.Debug|Win32.ActiveCfg = Debug|Win32 + {EA55446E-BC04-491C-A9F0-605DFCBB213A}.Debug|Win32.Build.0 = Debug|Win32 + {EA55446E-BC04-491C-A9F0-605DFCBB213A}.Release|Win32.ActiveCfg = Release|Win32 + {EA55446E-BC04-491C-A9F0-605DFCBB213A}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/utils/vprojtomake/vprojtomake.vcxproj b/utils/vprojtomake/vprojtomake.vcxproj new file mode 100644 index 00000000..c7f526b5 --- /dev/null +++ b/utils/vprojtomake/vprojtomake.vcxproj @@ -0,0 +1,297 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {EA55446E-BC04-491C-A9F0-605DFCBB213A} + + + + Application + false + MultiByte + v90 + + + Application + false + MultiByte + v90 + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\bin\ + .\Release\ + false + .\bin\ + .\Debug\ + true + vcpm + vcpm + + + + + + + + + + + + .\Release/vprojtomake.tlb + + + + + MaxSpeed + OnlyExplicitInline + ..\common;..\..\public;..\..\public\tier1;..\..\public\tier0;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + stdafx.h + .\Release/vprojtomake.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + Default + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + odbc32.lib;odbccp32.lib;comsupp.lib;msxml2.lib;comsuppw.lib;%(AdditionalDependencies) + $(TargetPath) + true + ..\..\lib\public;%(AdditionalLibraryDirectories) + LIBCMTD;%(IgnoreSpecificDefaultLibraries) + .\Release/vprojtomake.pdb + Console + false + + + MachineX86 + + + + + if exist ..\..\..\bin\vcpm.exe attrib -r ..\..\..\bin\vcpm.exe +if exist "$(TargetPath)" copy "$(TargetPath)" ..\..\..\bin\vcpm.exe + + ..\..\..\bin\vcpm.exe;%(Outputs) + + + .\Debug/vprojtomake.tlb + + + + + Disabled + ..\common;..\..\public;..\..\public\tier1;..\..\public\tier0;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;DEBUG;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + stdafx.h + .\Debug/vprojtomake.pch + .\Debug/ + .\Debug/ + .\Debug/ + true + .\Debug/ + Level4 + true + ProgramDatabase + Default + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + /FIXED:NO %(AdditionalOptions) + odbc32.lib;odbccp32.lib;msxml2.lib;comsuppw.lib;comsupp.lib;%(AdditionalDependencies) + $(TargetPath) + true + ..\..\lib\public;%(AdditionalLibraryDirectories) + LIBCMT;%(IgnoreSpecificDefaultLibraries) + true + .\Debug/vprojtomake.pdb + true + .\Debug/vprojtomake.map + Console + false + + + MachineX86 + + + + + Disabled + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + EnableFastChecks + + + true + MaxSpeed + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + + + + + Disabled + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + EnableFastChecks + + + true + MaxSpeed + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + + + + + Disabled + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + EnableFastChecks + + + true + MaxSpeed + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + + + Disabled + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + EnableFastChecks + + + true + MaxSpeed + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + + + + + Disabled + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + EnableFastChecks + + + true + MaxSpeed + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + + + + + Disabled + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + EnableFastChecks + + + true + MaxSpeed + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + + + + + + + + + Disabled + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + EnableFastChecks + + + true + MaxSpeed + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/utils/vprojtomake/vprojtomake.vcxproj.filters b/utils/vprojtomake/vprojtomake.vcxproj.filters new file mode 100644 index 00000000..c45f8766 --- /dev/null +++ b/utils/vprojtomake/vprojtomake.vcxproj.filters @@ -0,0 +1,121 @@ + + + + + {139d5f56-5207-4b42-a7c2-3283235db62b} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {e9b24255-482f-4d31-a13d-8ec74e8e07a4} + h;hpp;hxx;hm;inl + + + {6b7654c4-c2a0-4c3a-80b7-7a758ee84265} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\TinyXML + + + Source Files\TinyXML + + + Source Files\TinyXML + + + Source Files\TinyXML + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Source Files\TinyXML + + + Source Files\TinyXML + + + + + + + + + + + \ No newline at end of file