├── .vscode
└── settings.json
├── .clang-format
├── FortKitInsider
├── .clang-format
├── consts.h
├── FortKitInsider.vcxproj.user
├── framework.h
├── writer.h
├── util.h
├── parallel_hashmap
│ ├── conanfile.py
│ ├── meminfo.h
│ ├── phmap_fwd_decl.h
│ ├── phmap_dump.h
│ ├── phmap_utils.h
│ ├── phmap_bits.h
│ └── phmap_config.h
├── dllmain.cpp
├── exceptions.h
├── FortKitInsider.vcxproj.filters
├── usmap.h
├── ue4.cpp
├── generic.h
├── cppgenerator.h
├── .gitignore
├── FortKitInsider.vcxproj
├── dumper.h
├── enums.h
└── ue4.h
├── README.md
├── FortKit.sln
└── .gitignore
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.associations": {
3 | "xstring": "cpp"
4 | }
5 | }
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | BasedOnStyle: WebKit
3 | AlignAfterOpenBracket: DontAlign
4 | BreakBeforeBraces: Allman
5 | NamespaceIndentation: All
6 | SortIncludes: false
7 |
8 | ...
9 |
--------------------------------------------------------------------------------
/FortKitInsider/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | BasedOnStyle: WebKit
3 | AlignAfterOpenBracket: DontAlign
4 | BreakBeforeBraces: Allman
5 | NamespaceIndentation: All
6 | SortIncludes: false
7 |
8 | ...
9 |
--------------------------------------------------------------------------------
/FortKitInsider/consts.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace Patterns
4 | {
5 | constexpr auto GObjects = "48 8B 05 ? ? ? ? 48 8B 0C C8 48 8D 04 D1 EB";
6 | }
7 |
8 | namespace StringRefs
9 | {
10 | constexpr auto FNameToString = L"Loading Module %s";
11 | }
--------------------------------------------------------------------------------
/FortKitInsider/FortKitInsider.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 |
6 |
--------------------------------------------------------------------------------
/FortKitInsider/framework.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #define WIN32_LEAN_AND_MEAN
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include "ue4.h"
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FortKit
2 |
3 | Fortnite SDK dumper.
4 |
5 | - Usage:
6 | - Compile on x64 (preferly release for speed's sake) and inject in fortnite process with no AC.
7 | - It will output `Mappings.usmap` and `DUMP` folder in fortnite's win64 folder.
8 |
9 |
10 | - Future plans:
11 | - Dump each context in a file instead of each class in a file.
12 | - Walk on classes's native functions before dumping the class itself and extract the offsets it uses (usually it's rcx+offset).
13 | - Generate DLL project file that is useable directly without any reversing skill requirements.
14 |
--------------------------------------------------------------------------------
/FortKitInsider/writer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class FileWriter
4 | {
5 | FILE* m_File;
6 |
7 | public:
8 |
9 | FileWriter()
10 | {
11 | }
12 |
13 | FileWriter(const char* FileName)
14 | {
15 | fopen_s(&m_File, FileName, "wb");
16 | }
17 |
18 | ~FileWriter()
19 | {
20 | std::fclose(m_File);
21 | }
22 |
23 | void WriteString(std::string String)
24 | {
25 | std::fwrite(String.c_str(), String.length(), 1, m_File);
26 | }
27 |
28 | template
29 | void Write(T Input)
30 | {
31 | std::fwrite(&Input, sizeof(T), 1, m_File);
32 | }
33 |
34 | void Seek(int Pos, int Origin = SEEK_CUR)
35 | {
36 | std::fseek(m_File, Pos, Origin);
37 | }
38 |
39 | uint32_t Size()
40 | {
41 | auto pos = std::ftell(m_File);
42 | std::fseek(m_File, 0, SEEK_END);
43 | auto ret = std::ftell(m_File);
44 | std::fseek(m_File, pos, SEEK_SET);
45 | return ret;
46 | }
47 | };
48 |
--------------------------------------------------------------------------------
/FortKitInsider/util.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "framework.h"
3 |
4 | namespace Util
5 | {
6 | static void SetupConsole()
7 | {
8 | AllocConsole();
9 |
10 | FILE* pFile;
11 | freopen_s(&pFile, "CONOUT$", "w", stdout);
12 | // freopen_s(&pFile, "kkkk.log", "w", stdout);
13 | }
14 |
15 | static void FixName(std::string& name)
16 | {
17 | constexpr static std::string_view chars = " ?+_-:/^()[]<>^.#\'\"%";
18 |
19 | erase_if(name, [](const unsigned char c)
20 | { return chars.find(c) != std::string_view::npos; });
21 | }
22 |
23 | static void Spacing(std::string& str, const size_t size = 70, bool left = false)
24 | {
25 | if (size > str.size())
26 | {
27 | str.insert(left ? str.begin() : str.end(), size - str.size(), ' ');
28 | }
29 | }
30 |
31 | static bool IsBadReadPtr(void* p)
32 | {
33 | MEMORY_BASIC_INFORMATION mbi;
34 | if (VirtualQuery(p, &mbi, sizeof(mbi)))
35 | {
36 | DWORD mask = (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY);
37 | bool b = !(mbi.Protect & mask);
38 | if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS))
39 | b = true;
40 |
41 | return b;
42 | }
43 |
44 | return true;
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/FortKitInsider/parallel_hashmap/conanfile.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | from conans import ConanFile, tools
5 | import os
6 |
7 | class SparseppConan(ConanFile):
8 | name = "parallel_hashmap"
9 | version = "1.36"
10 | description = "A header-only, very fast and memory-friendly hash map"
11 | url = "https://github.com/greg7mdp/parallel-hashmap/blob/master/parallel_hashmap/conanfile.py"
12 |
13 | # Indicates License type of the packaged library
14 | license = "https://github.com/greg7mdp/parallel-hashmap/blob/master/LICENSE"
15 |
16 | # Packages the license for the conanfile.py
17 | exports = ["LICENSE"]
18 |
19 | # Custom attributes for Bincrafters recipe conventions
20 | source_subfolder = "source_subfolder"
21 |
22 | def source(self):
23 | source_url = "https://github.com/greg7mdp/parallel-hashmap"
24 | tools.get("{0}/archive/{1}.tar.gz".format(source_url, self.version))
25 | extracted_dir = self.name + "-" + self.version
26 |
27 | #Rename to "source_folder" is a convention to simplify later steps
28 | os.rename(extracted_dir, self.source_subfolder)
29 |
30 |
31 | def package(self):
32 | include_folder = os.path.join(self.source_subfolder, "parallel_hashmap")
33 | self.copy(pattern="LICENSE")
34 | self.copy(pattern="*", dst="include/parallel_hashmap", src=include_folder)
35 |
36 | def package_id(self):
37 | self.info.header_only()
38 |
--------------------------------------------------------------------------------
/FortKit.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.2.32616.157
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FortKitInsider", "FortKitInsider\FortKitInsider.vcxproj", "{09849E3E-CC19-40BD-8D25-DED5D5F7F55C}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {09849E3E-CC19-40BD-8D25-DED5D5F7F55C}.Debug|x64.ActiveCfg = Debug|x64
17 | {09849E3E-CC19-40BD-8D25-DED5D5F7F55C}.Debug|x64.Build.0 = Debug|x64
18 | {09849E3E-CC19-40BD-8D25-DED5D5F7F55C}.Debug|x86.ActiveCfg = Debug|Win32
19 | {09849E3E-CC19-40BD-8D25-DED5D5F7F55C}.Debug|x86.Build.0 = Debug|Win32
20 | {09849E3E-CC19-40BD-8D25-DED5D5F7F55C}.Release|x64.ActiveCfg = Release|x64
21 | {09849E3E-CC19-40BD-8D25-DED5D5F7F55C}.Release|x64.Build.0 = Release|x64
22 | {09849E3E-CC19-40BD-8D25-DED5D5F7F55C}.Release|x86.ActiveCfg = Release|Win32
23 | {09849E3E-CC19-40BD-8D25-DED5D5F7F55C}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {C6A761A2-5800-490C-BCE0-1D3A1D8FEE14}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/FortKitInsider/dllmain.cpp:
--------------------------------------------------------------------------------
1 | #include "consts.h"
2 | #include "dumper.h"
3 | #include "framework.h"
4 | #include "memory.h"
5 | #include "memcury.h"
6 | #include "exceptions.h"
7 |
8 | static void Main(HMODULE hModule)
9 | {
10 | Util::SetupConsole();
11 |
12 | Memcury::Safety::SetExceptionMode();
13 |
14 | auto Start = std::chrono::steady_clock::now();
15 |
16 | GObjects = Memcury::Scanner::FindPattern(Patterns::GObjects)
17 | .RelativeOffset(3)
18 | .GetAs();
19 |
20 | FNameToString = Memcury::Scanner::FindStringRef(StringRefs::FNameToString)
21 | .ScanFor({ Memcury::ASM::CALL }, false)
22 | .RelativeOffset(1)
23 | .GetAs();
24 |
25 | auto End = std::chrono::steady_clock::now();
26 |
27 | printf("[=] Init Time: %.02f ms\n", (End - Start).count() / 1000000.);
28 |
29 | Dumper::Dump();
30 | // Dumper::GenerateUsmap();
31 |
32 | FreeLibraryAndExitThread(hModule, 0);
33 | }
34 |
35 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
36 | {
37 | switch (ul_reason_for_call)
38 | {
39 | case DLL_PROCESS_ATTACH:
40 | {
41 | __try
42 | {
43 | Main(hModule);
44 | }
45 | __except (HandlerForCallStack(GetExceptionInformation()))
46 | {
47 | MessageBoxA(nullptr, "Main function crashed!", "Error", MB_ICONERROR | MB_OK);
48 | }
49 | break;
50 | }
51 | default:
52 | break;
53 | }
54 | return TRUE;
55 | }
56 |
--------------------------------------------------------------------------------
/FortKitInsider/exceptions.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #pragma comment(lib, "Dbghelp.lib")
4 |
5 | void printStack(CONTEXT* ctx)
6 | {
7 | STACKFRAME64 stack;
8 | memset(&stack, 0, sizeof(STACKFRAME64));
9 |
10 | auto process = GetCurrentProcess();
11 | auto thread = GetCurrentThread();
12 |
13 | SymInitialize(process, NULL, TRUE);
14 |
15 | bool result;
16 | DWORD64 displacement = 0;
17 |
18 | char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)] { 0 };
19 | char name[512] { 0 };
20 | char module[512] { 0 };
21 |
22 | PSYMBOL_INFO symbolInfo = (PSYMBOL_INFO)buffer;
23 |
24 | for (ULONG frame = 0;; frame++)
25 | {
26 | result = StackWalk64(
27 | IMAGE_FILE_MACHINE_AMD64,
28 | process,
29 | thread,
30 | &stack,
31 | ctx,
32 | NULL,
33 | SymFunctionTableAccess64,
34 | SymGetModuleBase64,
35 | NULL);
36 |
37 | if (!result)
38 | break;
39 |
40 | symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
41 | symbolInfo->MaxNameLen = MAX_SYM_NAME;
42 | SymFromAddr(process, (ULONG64)stack.AddrPC.Offset, &displacement, symbolInfo);
43 |
44 | HMODULE hModule = NULL;
45 | lstrcpyA(module, "");
46 | GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (const wchar_t*)(stack.AddrPC.Offset), &hModule);
47 |
48 | if (hModule != NULL)
49 | GetModuleFileNameA(hModule, module, 512);
50 |
51 | printf("[%lu] Name: %s - Address: %p - Module: %s\n", frame, symbolInfo->Name, (void*)symbolInfo->Address, module);
52 | }
53 | }
54 |
55 | int HandlerForCallStack(_EXCEPTION_POINTERS* ex)
56 | {
57 | printStack(ex->ContextRecord);
58 |
59 | return EXCEPTION_EXECUTE_HANDLER;
60 | }
--------------------------------------------------------------------------------
/FortKitInsider/FortKitInsider.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 | Header Files
35 |
36 |
37 | Header Files
38 |
39 |
40 | Header Files
41 |
42 |
43 | Header Files
44 |
45 |
46 | Header Files
47 |
48 |
49 | Header Files
50 |
51 |
52 | Header Files
53 |
54 |
55 |
56 |
57 | Source Files
58 |
59 |
60 | Header Files
61 |
62 |
63 |
--------------------------------------------------------------------------------
/FortKitInsider/parallel_hashmap/meminfo.h:
--------------------------------------------------------------------------------
1 | #if !defined(spp_memory_h_guard)
2 | #define spp_memory_h_guard
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #if defined(_WIN32) || defined( __CYGWIN__)
9 | #define SPP_WIN
10 | #endif
11 |
12 | #ifdef SPP_WIN
13 | #include
14 | #include
15 | #undef min
16 | #undef max
17 | #elif defined(__linux__)
18 | #include
19 | #include
20 | #elif defined(__FreeBSD__)
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #endif
28 |
29 | namespace spp
30 | {
31 | uint64_t GetSystemMemory();
32 | uint64_t GetTotalMemoryUsed();
33 | uint64_t GetProcessMemoryUsed();
34 | uint64_t GetPhysicalMemory();
35 |
36 | uint64_t GetSystemMemory()
37 | {
38 | #ifdef SPP_WIN
39 | MEMORYSTATUSEX memInfo;
40 | memInfo.dwLength = sizeof(MEMORYSTATUSEX);
41 | GlobalMemoryStatusEx(&memInfo);
42 | return static_cast(memInfo.ullTotalPageFile);
43 | #elif defined(__linux__)
44 | struct sysinfo memInfo;
45 | sysinfo (&memInfo);
46 | auto totalVirtualMem = memInfo.totalram;
47 |
48 | totalVirtualMem += memInfo.totalswap;
49 | totalVirtualMem *= memInfo.mem_unit;
50 | return static_cast(totalVirtualMem);
51 | #elif defined(__FreeBSD__)
52 | kvm_t *kd;
53 | u_int pageCnt;
54 | size_t pageCntLen = sizeof(pageCnt);
55 | u_int pageSize;
56 | struct kvm_swap kswap;
57 | uint64_t totalVirtualMem;
58 |
59 | pageSize = static_cast(getpagesize());
60 |
61 | sysctlbyname("vm.stats.vm.v_page_count", &pageCnt, &pageCntLen, NULL, 0);
62 | totalVirtualMem = pageCnt * pageSize;
63 |
64 | kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
65 | kvm_getswapinfo(kd, &kswap, 1, 0);
66 | kvm_close(kd);
67 | totalVirtualMem += kswap.ksw_total * pageSize;
68 |
69 | return totalVirtualMem;
70 | #else
71 | return 0;
72 | #endif
73 | }
74 |
75 | uint64_t GetTotalMemoryUsed()
76 | {
77 | #ifdef SPP_WIN
78 | MEMORYSTATUSEX memInfo;
79 | memInfo.dwLength = sizeof(MEMORYSTATUSEX);
80 | GlobalMemoryStatusEx(&memInfo);
81 | return static_cast(memInfo.ullTotalPageFile - memInfo.ullAvailPageFile);
82 | #elif defined(__linux__)
83 | struct sysinfo memInfo;
84 | sysinfo(&memInfo);
85 | auto virtualMemUsed = memInfo.totalram - memInfo.freeram;
86 |
87 | virtualMemUsed += memInfo.totalswap - memInfo.freeswap;
88 | virtualMemUsed *= memInfo.mem_unit;
89 |
90 | return static_cast(virtualMemUsed);
91 | #elif defined(__FreeBSD__)
92 | kvm_t *kd;
93 | u_int pageSize;
94 | u_int pageCnt, freeCnt;
95 | size_t pageCntLen = sizeof(pageCnt);
96 | size_t freeCntLen = sizeof(freeCnt);
97 | struct kvm_swap kswap;
98 | uint64_t virtualMemUsed;
99 |
100 | pageSize = static_cast(getpagesize());
101 |
102 | sysctlbyname("vm.stats.vm.v_page_count", &pageCnt, &pageCntLen, NULL, 0);
103 | sysctlbyname("vm.stats.vm.v_free_count", &freeCnt, &freeCntLen, NULL, 0);
104 | virtualMemUsed = (pageCnt - freeCnt) * pageSize;
105 |
106 | kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
107 | kvm_getswapinfo(kd, &kswap, 1, 0);
108 | kvm_close(kd);
109 | virtualMemUsed += kswap.ksw_used * pageSize;
110 |
111 | return virtualMemUsed;
112 | #else
113 | return 0;
114 | #endif
115 | }
116 |
117 | uint64_t GetProcessMemoryUsed()
118 | {
119 | #ifdef SPP_WIN
120 | PROCESS_MEMORY_COUNTERS_EX pmc;
121 | GetProcessMemoryInfo(GetCurrentProcess(), reinterpret_cast(&pmc), sizeof(pmc));
122 | return static_cast(pmc.PrivateUsage);
123 | #elif defined(__linux__)
124 | auto parseLine =
125 | [](char* line)->int
126 | {
127 | auto i = strlen(line);
128 |
129 | while(*line < '0' || *line > '9')
130 | {
131 | line++;
132 | }
133 |
134 | line[i-3] = '\0';
135 | i = atoi(line);
136 | return i;
137 | };
138 |
139 | auto file = fopen("/proc/self/status", "r");
140 | auto result = -1;
141 | char line[128];
142 |
143 | while(fgets(line, 128, file) != nullptr)
144 | {
145 | if(strncmp(line, "VmSize:", 7) == 0)
146 | {
147 | result = parseLine(line);
148 | break;
149 | }
150 | }
151 |
152 | fclose(file);
153 | return static_cast(result) * 1024;
154 | #elif defined(__FreeBSD__)
155 | struct kinfo_proc info;
156 | size_t infoLen = sizeof(info);
157 | int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
158 |
159 | sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &infoLen, NULL, 0);
160 | return static_cast(info.ki_rssize * getpagesize());
161 | #else
162 | return 0;
163 | #endif
164 | }
165 |
166 | uint64_t GetPhysicalMemory()
167 | {
168 | #ifdef SPP_WIN
169 | MEMORYSTATUSEX memInfo;
170 | memInfo.dwLength = sizeof(MEMORYSTATUSEX);
171 | GlobalMemoryStatusEx(&memInfo);
172 | return static_cast(memInfo.ullTotalPhys);
173 | #elif defined(__linux__)
174 | struct sysinfo memInfo;
175 | sysinfo(&memInfo);
176 |
177 | auto totalPhysMem = memInfo.totalram;
178 |
179 | totalPhysMem *= memInfo.mem_unit;
180 | return static_cast(totalPhysMem);
181 | #elif defined(__FreeBSD__)
182 | u_long physMem;
183 | size_t physMemLen = sizeof(physMem);
184 | int mib[] = { CTL_HW, HW_PHYSMEM };
185 |
186 | sysctl(mib, sizeof(mib) / sizeof(*mib), &physMem, &physMemLen, NULL, 0);
187 | return physMem;
188 | #else
189 | return 0;
190 | #endif
191 | }
192 |
193 | }
194 |
195 | #endif // spp_memory_h_guard
196 |
--------------------------------------------------------------------------------
/FortKitInsider/usmap.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "writer.h"
4 |
5 | class Usmap
6 | {
7 | FileWriter m_Writer = "Mappings.usmap";
8 | phmap::flat_hash_map m_Names;
9 |
10 | struct PropData
11 | {
12 | FProperty* Prop;
13 | uint16_t Index;
14 | uint8_t ArrayDim;
15 | FName Name;
16 | EPropertyType Type;
17 |
18 | PropData(FProperty* p, int idx) :
19 | Prop(p),
20 | Index(idx),
21 | ArrayDim(p->ArrayDim),
22 | Name(p->NamePrivate),
23 | Type(p->GetPropertyType())
24 | {
25 | }
26 | };
27 |
28 | void GetStructNames(UStruct*& Struct)
29 | {
30 | m_Names.insert_or_assign(Struct->NamePrivate, 0);
31 |
32 | if (Struct->SuperStruct && !m_Names.contains(Struct->SuperStruct->NamePrivate))
33 | m_Names.insert_or_assign(Struct->SuperStruct->NamePrivate, 0);
34 |
35 | auto prop = (FProperty*)Struct->ChildProperties;
36 |
37 | while (prop)
38 | {
39 | m_Names.insert_or_assign(prop->NamePrivate, 0);
40 | prop = (FProperty*)prop->Next;
41 | }
42 | }
43 |
44 | void GetEnumNames(UEnum*& Enum)
45 | {
46 | m_Names.insert_or_assign(Enum->NamePrivate, 0);
47 |
48 | for (int i = 0; i < Enum->Names.Num(); i++)
49 | {
50 | m_Names.insert_or_assign(Enum->Names[i].Key, 0);
51 | }
52 | }
53 |
54 | void WritePropertyTypeInfo(FProperty*& Prop, EPropertyType& Type)
55 | {
56 | FProperty* Inner = nullptr;
57 | EPropertyType InnerType = EPropertyType::Unknown;
58 | FProperty* Value = nullptr;
59 | EPropertyType ValueType = EPropertyType::Unknown;
60 |
61 | if (Type == EnumAsByteProperty)
62 | {
63 | m_Writer.Write(EnumProperty);
64 | }
65 | else
66 | {
67 | m_Writer.Write(Type);
68 | }
69 |
70 | switch (Type)
71 | {
72 | case EnumProperty:
73 | {
74 | Inner = ((FEnumProperty*)Prop)->UnderlyingProp;
75 | InnerType = Inner->GetPropertyType();
76 | WritePropertyTypeInfo(Inner, InnerType);
77 | m_Writer.Write(m_Names[reinterpret_cast(Prop)->Enum->NamePrivate]);
78 | break;
79 | }
80 | case EnumAsByteProperty:
81 | {
82 | m_Writer.Write(ByteProperty);
83 | m_Writer.Write(m_Names[((FByteProperty*)Prop)->Enum->NamePrivate]);
84 | break;
85 | }
86 | case StructProperty:
87 | {
88 | m_Writer.Write(m_Names[((FStructProperty*)Prop)->Struct->NamePrivate]);
89 | break;
90 | }
91 | case SetProperty:
92 | case ArrayProperty:
93 | {
94 | Inner = ((FArrayProperty*)Prop)->Inner;
95 | InnerType = Inner->GetPropertyType();
96 | WritePropertyTypeInfo(Inner, InnerType);
97 | break;
98 | }
99 | case MapProperty:
100 | {
101 | Inner = ((FMapProperty*)Prop)->KeyProp;
102 | InnerType = Inner->GetPropertyType();
103 | WritePropertyTypeInfo(Inner, InnerType);
104 |
105 | Value = ((FMapProperty*)Prop)->ValueProp;
106 | ValueType = Value->GetPropertyType();
107 | WritePropertyTypeInfo(Value, ValueType);
108 | break;
109 | }
110 | }
111 | }
112 |
113 | void HandleProperty(PropData& Prop)
114 | {
115 | m_Writer.Write(Prop.Index);
116 | m_Writer.Write(Prop.ArrayDim);
117 | m_Writer.Write(m_Names[Prop.Name]);
118 |
119 | WritePropertyTypeInfo(Prop.Prop, Prop.Type);
120 | }
121 |
122 | public:
123 | void Generate() // i'm kind of finicky about this code but it's quick and gets the job done
124 | {
125 | m_Names.reserve(90000);
126 | std::vector Enums;
127 | Enums.reserve(2500);
128 | std::vector Structs;
129 | Structs.reserve(15000);
130 |
131 | for (int i = 0; i < GObjects->NumElements; i++)
132 | {
133 | auto object = GObjects->GetByIndex(i);
134 | if (object == nullptr)
135 | {
136 | continue;
137 | }
138 |
139 | if (object->Class == UClass::StaticClass() ||
140 | object->Class == UScriptStruct::StaticClass())
141 | {
142 | auto Struct = static_cast(object);
143 |
144 | if (Struct->Outer && Struct->Outer->Class == UAnimBlueprintGeneratedClass::StaticClass()) //filter weird results
145 | continue;
146 |
147 | Structs.push_back(Struct);
148 | GetStructNames(Struct);
149 | }
150 | else if (object->Class == UEnum::StaticClass())
151 | {
152 | auto Enum = static_cast(object);
153 | Enums.push_back(Enum);
154 | GetEnumNames(Enum);
155 | }
156 | }
157 |
158 | m_Writer.Write(0); //overwrite this later with magic, file size, etc
159 | m_Writer.Write(0);
160 |
161 | m_Writer.Write(m_Names.size());
162 | int CurrentNameIndex = 0;
163 |
164 | for (auto N : m_Names)
165 | {
166 | m_Names[N.first] = CurrentNameIndex; //assign an index to each name in the hash table
167 | auto Name = N.first.ToString();
168 |
169 | auto Find = Name.find("::");
170 | if (Find != std::string::npos)
171 | {
172 | Name = Name.substr(Find + 2);
173 | }
174 |
175 | m_Writer.Write(Name.length());
176 | m_Writer.WriteString(Name);
177 |
178 | CurrentNameIndex++;
179 | }
180 |
181 | m_Writer.Write(Enums.size());
182 |
183 | for (auto Enum : Enums)
184 | {
185 | m_Writer.Write(m_Names[Enum->NamePrivate]);
186 | m_Writer.Write(Enum->Names.Num());
187 |
188 | for (int i = 0; i < Enum->Names.Num(); i++)
189 | {
190 | m_Writer.Write(m_Names[Enum->Names[i].Key]);
191 | }
192 | }
193 |
194 | m_Writer.Write(Structs.size());
195 |
196 | for (auto Struct : Structs)
197 | {
198 | m_Writer.Write(m_Names[Struct->NamePrivate]);
199 | m_Writer.Write(Struct->SuperStruct ? m_Names[Struct->SuperStruct->NamePrivate] : 0xffffffff);
200 |
201 | std::vector Properties;
202 |
203 | auto Prop = (FProperty*)Struct->ChildProperties;
204 | unsigned short PropCount = 0;
205 | unsigned short SerializablePropCount = 0;
206 |
207 | while (Prop)
208 | {
209 | PropData Data(Prop, PropCount);
210 |
211 | Properties.push_back(Data);
212 | Prop = (FProperty*)Prop->Next;
213 |
214 | PropCount += Data.ArrayDim;
215 | SerializablePropCount++;
216 | }
217 |
218 | m_Writer.Write(PropCount);
219 | m_Writer.Write(SerializablePropCount);
220 |
221 | for (auto p : Properties)
222 | {
223 | HandleProperty(p);
224 | }
225 | }
226 |
227 | m_Writer.Seek(0, SEEK_SET);
228 | m_Writer.Write(0x30C4); //magic
229 | m_Writer.Write(0); //version
230 | m_Writer.Write(0); //compression
231 | m_Writer.Write(m_Writer.Size() - 12); //compressed size
232 | m_Writer.Write(m_Writer.Size() - 12); //decompressed size
233 | }
234 | };
235 |
--------------------------------------------------------------------------------
/FortKitInsider/parallel_hashmap/phmap_fwd_decl.h:
--------------------------------------------------------------------------------
1 | #if !defined(phmap_fwd_decl_h_guard_)
2 | #define phmap_fwd_decl_h_guard_
3 |
4 | // ---------------------------------------------------------------------------
5 | // Copyright (c) 2019, Gregory Popovitch - greg7mdp@gmail.com
6 | //
7 | // Licensed under the Apache License, Version 2.0 (the "License");
8 | // you may not use this file except in compliance with the License.
9 | // You may obtain a copy of the License at
10 | //
11 | // https://www.apache.org/licenses/LICENSE-2.0
12 | // ---------------------------------------------------------------------------
13 |
14 | #ifdef _MSC_VER
15 | #pragma warning(push)
16 | #pragma warning(disable : 4514) // unreferenced inline function has been removed
17 | #pragma warning(disable : 4710) // function not inlined
18 | #pragma warning(disable : 4711) // selected for automatic inline expansion
19 | #endif
20 |
21 | #include
22 | #include
23 |
24 | #if defined(PHMAP_USE_ABSL_HASH) && !defined(ABSL_HASH_HASH_H_)
25 | namespace absl { template struct Hash; };
26 | #endif
27 |
28 | namespace phmap {
29 |
30 | #if defined(PHMAP_USE_ABSL_HASH)
31 | template using Hash = ::absl::Hash;
32 | #else
33 | template struct Hash;
34 | #endif
35 |
36 | template struct EqualTo;
37 | template struct Less;
38 | template using Allocator = typename std::allocator;
39 | template using Pair = typename std::pair;
40 |
41 | class NullMutex;
42 |
43 | namespace priv {
44 |
45 | // The hash of an object of type T is computed by using phmap::Hash.
46 | template
47 | struct HashEq
48 | {
49 | using Hash = phmap::Hash;
50 | using Eq = phmap::EqualTo;
51 | };
52 |
53 | template
54 | using hash_default_hash = typename priv::HashEq::Hash;
55 |
56 | template
57 | using hash_default_eq = typename priv::HashEq::Eq;
58 |
59 | // type alias for std::allocator so we can forward declare without including other headers
60 | template
61 | using Allocator = typename phmap::Allocator;
62 |
63 | // type alias for std::pair so we can forward declare without including other headers
64 | template
65 | using Pair = typename phmap::Pair;
66 |
67 | } // namespace priv
68 |
69 | // ------------- forward declarations for hash containers ----------------------------------
70 | template ,
72 | class Eq = phmap::priv::hash_default_eq,
73 | class Alloc = phmap::priv::Allocator> // alias for std::allocator
74 | class flat_hash_set;
75 |
76 | template ,
78 | class Eq = phmap::priv::hash_default_eq,
79 | class Alloc = phmap::priv::Allocator<
80 | phmap::priv::Pair>> // alias for std::allocator
81 | class flat_hash_map;
82 |
83 | template ,
85 | class Eq = phmap::priv::hash_default_eq,
86 | class Alloc = phmap::priv::Allocator> // alias for std::allocator
87 | class node_hash_set;
88 |
89 | template ,
91 | class Eq = phmap::priv::hash_default_eq,
92 | class Alloc = phmap::priv::Allocator<
93 | phmap::priv::Pair>> // alias for std::allocator
94 | class node_hash_map;
95 |
96 | template ,
98 | class Eq = phmap::priv::hash_default_eq,
99 | class Alloc = phmap::priv::Allocator, // alias for std::allocator
100 | size_t N = 4, // 2**N submaps
101 | class Mutex = phmap::NullMutex> // use std::mutex to enable internal locks
102 | class parallel_flat_hash_set;
103 |
104 | template ,
106 | class Eq = phmap::priv::hash_default_eq,
107 | class Alloc = phmap::priv::Allocator<
108 | phmap::priv::Pair>, // alias for std::allocator
109 | size_t N = 4, // 2**N submaps
110 | class Mutex = phmap::NullMutex> // use std::mutex to enable internal locks
111 | class parallel_flat_hash_map;
112 |
113 | template ,
115 | class Eq = phmap::priv::hash_default_eq,
116 | class Alloc = phmap::priv::Allocator, // alias for std::allocator
117 | size_t N = 4, // 2**N submaps
118 | class Mutex = phmap::NullMutex> // use std::mutex to enable internal locks
119 | class parallel_node_hash_set;
120 |
121 | template ,
123 | class Eq = phmap::priv::hash_default_eq,
124 | class Alloc = phmap::priv::Allocator<
125 | phmap::priv::Pair>, // alias for std::allocator
126 | size_t N = 4, // 2**N submaps
127 | class Mutex = phmap::NullMutex> // use std::mutex to enable internal locks
128 | class parallel_node_hash_map;
129 |
130 | // ------------- forward declarations for btree containers ----------------------------------
131 | template ,
132 | typename Alloc = phmap::Allocator>
133 | class btree_set;
134 |
135 | template ,
136 | typename Alloc = phmap::Allocator>
137 | class btree_multiset;
138 |
139 | template ,
140 | typename Alloc = phmap::Allocator>>
141 | class btree_map;
142 |
143 | template ,
144 | typename Alloc = phmap::Allocator>>
145 | class btree_multimap;
146 |
147 | } // namespace phmap
148 |
149 |
150 | #ifdef _MSC_VER
151 | #pragma warning(pop)
152 | #endif
153 |
154 | #endif // phmap_fwd_decl_h_guard_
155 |
--------------------------------------------------------------------------------
/FortKitInsider/ue4.cpp:
--------------------------------------------------------------------------------
1 | #include "ue4.h"
2 |
3 | UClass* UClass::StaticClass()
4 | {
5 | static auto c = FindObject("Class /Script/CoreUObject.Class");
6 | return c;
7 | }
8 |
9 | UClass* UBlueprintGeneratedClass::StaticClass()
10 | {
11 | static auto c = FindObject("Class /Script/Engine.BlueprintGeneratedClass");
12 | return c;
13 | }
14 |
15 | UClass* UAnimBlueprintGeneratedClass::StaticClass()
16 | {
17 | static auto c = FindObject("Class /Script/Engine.AnimBlueprintGeneratedClass");
18 | return c;
19 | }
20 |
21 | UClass* UField::StaticClass()
22 | {
23 | static auto c = FindObject("Class /Script/CoreUObject.Field");
24 | return c;
25 | }
26 |
27 | UClass* UStruct::StaticClass()
28 | {
29 | static auto c = (UClass*)FindObject("Class /Script/CoreUObject.Struct");
30 | return c;
31 | }
32 |
33 | UClass* UFunction::StaticClass()
34 | {
35 | static auto c = FindObject("Class /Script/CoreUObject.Function");
36 | return c;
37 | }
38 |
39 | UClass* UEnum::StaticClass()
40 | {
41 | static auto c = FindObject("Class /Script/CoreUObject.Enum");
42 | return c;
43 |
44 | }
45 |
46 | UClass* UScriptStruct::StaticClass()
47 | {
48 | static auto c = FindObject("Class /Script/CoreUObject.ScriptStruct");
49 | return c;
50 |
51 | }
52 |
53 | template
54 | bool UObject::IsA() const
55 | {
56 | auto cmp = T::StaticClass();
57 | if (!cmp->IsValid())
58 | {
59 | return false;
60 | }
61 |
62 | for (auto super = (UStruct*)this->Class; super->IsValid(); super = super->SuperStruct)
63 | {
64 | if (super == cmp)
65 | {
66 | return true;
67 | }
68 | }
69 |
70 | return false;
71 | }
72 |
73 | bool UObject::IsA(UClass* cmp) const
74 | {
75 | if (!cmp->IsValid())
76 | {
77 | return false;
78 | }
79 |
80 | for (auto super = (UStruct*)this->Class; super->IsValid(); super = super->SuperStruct)
81 | {
82 | if (super == cmp)
83 | {
84 | return true;
85 | }
86 | }
87 |
88 | return false;
89 | }
90 |
91 | std::string UObject::GetCPPName()
92 | {
93 | std::string ret;
94 |
95 | if (IsA())
96 | {
97 | auto c = Cast();
98 | while (c->IsValid())
99 | {
100 | const auto className = c->GetName();
101 | if (className == "Actor")
102 | {
103 | ret += "A";
104 | break;
105 | }
106 |
107 | if (className == "Interface")
108 | {
109 | ret += "I";
110 | break;
111 | }
112 |
113 | if (className == "Object")
114 | {
115 | ret += "U";
116 | break;
117 | }
118 |
119 | c = c->SuperStruct->Cast();
120 | }
121 | }
122 | else
123 | {
124 | ret += "F";
125 | }
126 |
127 | ret += GetName();
128 |
129 | return ret;
130 | }
131 |
132 | bool GlobalObjects::TryFindObject(std::string startOfName, UObject& out)
133 | {
134 | if (startOfName.empty()) return false;
135 |
136 | for (int i = 0; i < NumElements; i++)
137 | {
138 | auto obj = GetByIndex(i);
139 | if (!obj) continue;
140 |
141 | auto name = obj->GetFullName();
142 |
143 | if (startOfName[0] != name[0]) continue;
144 | if (name.starts_with(startOfName))
145 | {
146 | out = *obj;
147 | return true;
148 | }
149 | }
150 |
151 | return false;
152 | }
153 |
154 | bool GlobalObjects::TryFindObjectByName(std::string name, UObject& out)
155 | {
156 | if (name.empty()) return false;
157 |
158 | for (int i = 0; i < NumElements; i++)
159 | {
160 | auto obj = GetByIndex(i);
161 | if (!obj) continue;
162 |
163 | auto objName = GetNameSafe(obj);
164 |
165 | if (name[0] != objName[0]) continue;
166 | if (name.compare(objName) == 0)
167 | {
168 | out = *obj;
169 | return true;
170 | }
171 | }
172 |
173 | return false;
174 | }
175 |
176 | EPropertyType FProperty::GetPropertyType()
177 | {
178 | switch (this->ClassPrivate->Id)
179 | {
180 | case FFieldClassID::Object:
181 | case FFieldClassID::ObjectPointer:
182 | case FFieldClassID::Class:
183 | {
184 | return EPropertyType::ObjectProperty;
185 | break;
186 | }
187 |
188 | case FFieldClassID::Struct:
189 | {
190 | return EPropertyType::StructProperty;
191 | break;
192 | }
193 |
194 | case FFieldClassID::Int8:
195 | {
196 | return EPropertyType::Int8Property;
197 | break;
198 | }
199 |
200 | case FFieldClassID::Int16:
201 | {
202 | return EPropertyType::Int16Property;
203 | break;
204 | }
205 |
206 | case FFieldClassID::Int:
207 | {
208 | return EPropertyType::IntProperty;
209 | break;
210 | }
211 |
212 | case FFieldClassID::Int64:
213 | {
214 | return EPropertyType::Int64Property;
215 | break;
216 | }
217 |
218 | case FFieldClassID::UInt16:
219 | {
220 | return EPropertyType::UInt16Property;
221 | break;
222 | }
223 |
224 | case FFieldClassID::UInt32:
225 | {
226 | return EPropertyType::UInt32Property;
227 | break;
228 | }
229 |
230 | case FFieldClassID::UInt64:
231 | {
232 | return EPropertyType::UInt64Property;
233 | break;
234 | }
235 |
236 | case FFieldClassID::Array:
237 | {
238 | return EPropertyType::ArrayProperty;
239 | break;
240 | }
241 |
242 | case FFieldClassID::Float:
243 | {
244 | return EPropertyType::FloatProperty;
245 | break;
246 | }
247 |
248 | case FFieldClassID::Double:
249 | {
250 | return EPropertyType::DoubleProperty;
251 | break;
252 | }
253 |
254 | case FFieldClassID::Bool:
255 | {
256 | return EPropertyType::BoolProperty;
257 | break;
258 | }
259 |
260 | case FFieldClassID::String:
261 | {
262 | return EPropertyType::StrProperty;
263 | break;
264 | }
265 |
266 | case FFieldClassID::Name:
267 | {
268 | return EPropertyType::NameProperty;
269 | break;
270 | }
271 |
272 | case FFieldClassID::Text:
273 | {
274 | return EPropertyType::TextProperty;
275 | break;
276 | }
277 |
278 | case FFieldClassID::Enum:
279 | {
280 | return EPropertyType::EnumProperty;
281 | break;
282 | }
283 |
284 | case FFieldClassID::Interface:
285 | {
286 | return EPropertyType::InterfaceProperty;
287 | break;
288 | }
289 |
290 | case FFieldClassID::Map:
291 | {
292 | return EPropertyType::MapProperty;
293 | break;
294 | }
295 |
296 | case FFieldClassID::Byte:
297 | {
298 | auto bprop = reinterpret_cast(this);
299 |
300 | if (bprop->Enum->IsValid())
301 | {
302 | return EPropertyType::EnumAsByteProperty;
303 | }
304 |
305 | return EPropertyType::ByteProperty;
306 | break;
307 | }
308 |
309 | case FFieldClassID::MulticastSparseDelegate:
310 | {
311 | return EPropertyType::MulticastDelegateProperty;
312 | break;
313 | }
314 | case FFieldClassID::Delegate:
315 | {
316 | return EPropertyType::DelegateProperty;
317 | break;
318 | }
319 | case FFieldClassID::SoftObject:
320 | case FFieldClassID::SoftClass:
321 | case FFieldClassID::WeakObject:
322 | {
323 | return EPropertyType::SoftObjectProperty;
324 | break;
325 | }
326 | /*case FFieldClassID::WeakObject:
327 | {
328 | return EPropertyType::WeakObjectProperty;
329 | break;
330 | }*/
331 | case FFieldClassID::LazyObject:
332 | {
333 | return EPropertyType::LazyObjectProperty;
334 | break;
335 | }
336 | case FFieldClassID::Set:
337 | {
338 | EPropertyType::SetProperty;
339 | break;
340 | }
341 | default:
342 | {
343 | return EPropertyType::Unknown;
344 | }
345 | }
346 | }
--------------------------------------------------------------------------------
/FortKitInsider/generic.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "framework.h"
3 |
4 | namespace Generic
5 | {
6 | std::string StringifyPropType(FProperty* prop)
7 | {
8 | std::string ret;
9 |
10 | switch (prop->ClassPrivate->Id)
11 | {
12 | case FFieldClassID::Object:
13 | case FFieldClassID::ObjectPointer:
14 | case FFieldClassID::Class:
15 | {
16 | ret += "class " + reinterpret_cast(prop)->PropertyClass->GetCPPName() + (prop->ElementSize == 0x8 ? "*" : "");
17 | break;
18 | }
19 |
20 | case FFieldClassID::Struct:
21 | {
22 | ret += "struct " + reinterpret_cast(prop)->Struct->GetCPPName() + (prop->ElementSize == 0x8 ? "*" : "");
23 | break;
24 | }
25 |
26 | case FFieldClassID::Int8:
27 | {
28 | ret += "int8_t";
29 | break;
30 | }
31 |
32 | case FFieldClassID::Int16:
33 | {
34 | ret += "int16_t";
35 | break;
36 | }
37 |
38 | case FFieldClassID::Int:
39 | {
40 | ret += "int";
41 | break;
42 | }
43 |
44 | case FFieldClassID::Int64:
45 | {
46 | ret += "int64_t";
47 | break;
48 | }
49 |
50 | case FFieldClassID::UInt16:
51 | {
52 | ret += "uint16_t";
53 | break;
54 | }
55 |
56 | case FFieldClassID::UInt32:
57 | {
58 | ret += "uint32_t";
59 | break;
60 | }
61 |
62 | case FFieldClassID::UInt64:
63 | {
64 | ret += "uint64_t";
65 | break;
66 | }
67 |
68 | case FFieldClassID::Array:
69 | {
70 | ret += "struct TArray<" + StringifyPropType(reinterpret_cast(prop)->Inner) + ">";
71 |
72 | break;
73 | }
74 |
75 | case FFieldClassID::Float:
76 | {
77 | ret += "float";
78 | break;
79 | }
80 |
81 | case FFieldClassID::Double:
82 | {
83 | ret += "double";
84 | break;
85 | }
86 |
87 | case FFieldClassID::Bool:
88 | {
89 | if (reinterpret_cast(prop)->IsNativeBool())
90 | {
91 | ret += "bool";
92 | }
93 | else
94 | {
95 | ret += "unsigned char";
96 | }
97 | break;
98 | }
99 |
100 | case FFieldClassID::String:
101 | {
102 | ret += "struct FString";
103 | break;
104 | }
105 |
106 | case FFieldClassID::Name:
107 | {
108 | ret += "struct FName";
109 | break;
110 | }
111 |
112 | case FFieldClassID::Text:
113 | {
114 | ret += "struct FText";
115 | break;
116 | }
117 |
118 | case FFieldClassID::Enum:
119 | {
120 | ret += "enum " + reinterpret_cast(prop)->Enum->GetName();
121 | break;
122 | }
123 |
124 | case FFieldClassID::Interface:
125 | {
126 | ret += "struct TScriptInterface(prop)->InterfaceClass->GetCPPName() + ">";
127 | break;
128 | }
129 |
130 | case FFieldClassID::Map:
131 | {
132 | auto mprop = reinterpret_cast(prop);
133 | auto keytype = StringifyPropType(mprop->KeyProp);
134 | auto valuetype = StringifyPropType(mprop->ValueProp);
135 |
136 | if (!keytype.empty() && !valuetype.empty())
137 | {
138 | ret += "struct TMap<" + keytype + ", " + valuetype + ">";
139 | }
140 | break;
141 | }
142 |
143 | case FFieldClassID::Byte:
144 | {
145 | auto bprop = reinterpret_cast(prop);
146 |
147 | if (bprop->Enum->IsValid())
148 | {
149 | ret += "struct TEnumAsByte<" + bprop->Enum->GetName() + ">";
150 | }
151 | else
152 | {
153 | ret += "unsigned char";
154 | }
155 |
156 | break;
157 | }
158 | case FFieldClassID::Delegate:
159 | {
160 | ret += "struct FDelegate";
161 | break;
162 | }
163 | case FFieldClassID::MulticastInlineDelegate:
164 | {
165 | ret += "struct FMulticastInlineDelegate";
166 | break;
167 | }
168 | case FFieldClassID::MulticastSparseDelegate:
169 | {
170 | ret += "struct FMulticastSparseDelegate";
171 | break;
172 | }
173 | /*
174 | case MULTICASTS_INLINE_DELEGATE_PROP_ID:
175 | {
176 | ret += "FMulticastSparseDelegate";
177 | break;
178 | }
179 | */
180 | case FFieldClassID::SoftObject:
181 |
182 | {
183 | ret += "struct TWeakObjectPtr(prop)->PropertyClass->GetCPPName() + ">";
184 | break;
185 | }
186 | case FFieldClassID::SoftClass:
187 |
188 | {
189 | ret += "struct TWeakObjectPtr(prop)->MetaClass->GetCPPName() + ">";
190 | break;
191 | }
192 | case FFieldClassID::WeakObject:
193 |
194 | {
195 | ret += "struct TWeakObjectPtr(prop)->PropertyClass->GetCPPName() + ">";
196 | break;
197 | }
198 | case FFieldClassID::LazyObject:
199 |
200 | {
201 | ret += "struct TLazyObjectPtr(prop)->PropertyClass->GetCPPName() + ">";
202 | break;
203 | }
204 | case FFieldClassID::Set:
205 |
206 | {
207 | ret += "struct TSet<" + StringifyPropType(reinterpret_cast(prop)->ElementProp) + ">";
208 | break;
209 | }
210 | default:;
211 | }
212 |
213 | return ret;
214 | }
215 |
216 | static auto StringifyFlags(uint32_t Flags)
217 | {
218 | constexpr static const char* FunctionFlags[32] = { "Final", "0x00000002", "BlueprintAuthorityOnly", "BlueprintCosmetic", "0x00000010", "0x00000020", "Net", "NetReliable", "NetRequest", "Exec", "Native", "Event", "NetResponse", "Static", "NetMulticast", "0x00008000", "MulticastDelegate", "Public", "Private", "Protected", "Delegate", "NetServer", "HasOutParms", "HasDefaults", "NetClient", "DLLImport", "BlueprintCallable", "BlueprintEvent", "BlueprintPure", "0x20000000", "Const", "0x80000000" };
219 |
220 | std::string FlagsA = "(";
221 |
222 | for (int32_t i = 0; i < 32; ++i)
223 | {
224 | const uint32_t Mask = 1U << i;
225 | if ((Flags & Mask) != 0)
226 | {
227 | FlagsA += FunctionFlags[i];
228 |
229 | FlagsA += " | ";
230 | }
231 | }
232 |
233 | if (FlagsA.size() > 1)
234 | {
235 | FlagsA.pop_back();
236 | FlagsA.pop_back();
237 | FlagsA.pop_back();
238 | }
239 |
240 | FlagsA += ")";
241 |
242 | return FlagsA;
243 | }
244 | }
245 |
--------------------------------------------------------------------------------
/FortKitInsider/cppgenerator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | namespace CPPGenerator
12 | {
13 | // https://ctrpeach.io/posts/cpp20-string-literal-template-parameters/
14 | template
15 | struct StringLiteral
16 | {
17 | constexpr StringLiteral(const char (&str)[N])
18 | {
19 | std::copy_n(str, N, value);
20 | }
21 |
22 | char value[N];
23 | };
24 |
25 | class Variable
26 | {
27 | public:
28 | std::string type;
29 | std::string name;
30 | bool isPtr = false;
31 | bool isRef = false;
32 | bool isStatic = false;
33 | bool isConst = false;
34 | bool isConstexpr = false;
35 | bool isStruct = false;
36 | bool isArray = false;
37 | int arraySize = 1;
38 | bool isBitField = false;
39 | int bitFieldSize = 1;
40 | std::string comment;
41 |
42 | private:
43 | Variable(std ::string Type, std ::string Name)
44 | : type(Type)
45 | , name(Name)
46 | {
47 | }
48 |
49 | public:
50 | template
51 | constexpr static auto New(std::string name) -> Variable
52 | {
53 | constexpr auto typeName = lit.value;
54 | return Variable(typeName, name);
55 | }
56 |
57 | template
58 | constexpr static auto New(std::string name) -> Variable
59 | {
60 | return Variable(typeid(T).name(), name);
61 | }
62 |
63 | static auto New(std::string type, std::string name) -> Variable
64 | {
65 | return Variable(type, name);
66 | }
67 | };
68 |
69 | class Header
70 | {
71 | bool isInNamespace;
72 | bool isInStruct;
73 | bool isInClass;
74 |
75 | std::vector generatedStructs;
76 | std::vector generatedClasses;
77 |
78 | std::queue> queuedStructs;
79 |
80 | std::string fileName;
81 | std::stringstream file;
82 |
83 | public:
84 | Header(std::string _fileName)
85 | : fileName(_fileName)
86 | {
87 | }
88 |
89 | ~Header()
90 | {
91 | std::fstream out;
92 | out.open(fileName + ".h", std::fstream::out | std::fstream::trunc);
93 |
94 | out << file.rdbuf();
95 | out.close();
96 | }
97 |
98 | auto AddText(std::string text)
99 | {
100 | file << text;
101 | }
102 |
103 | auto isAlreadyGeneratedStruct(std::string name)
104 | {
105 | for (auto&& str : generatedStructs)
106 | {
107 | if (str == name)
108 | {
109 | return true;
110 | }
111 | }
112 |
113 | return false;
114 | }
115 |
116 | auto isAlreadyGeneratedClass(std::string name)
117 | {
118 | for (auto&& str : generatedClasses)
119 | {
120 | if (str == name)
121 | {
122 | return true;
123 | }
124 | }
125 |
126 | return false;
127 | }
128 |
129 | auto queueStruct(std::function lambda)
130 | {
131 | queuedStructs.push(lambda);
132 | }
133 |
134 | void flushStructs()
135 | {
136 | while (!queuedStructs.empty())
137 | {
138 | queuedStructs.front()();
139 | queuedStructs.pop();
140 | }
141 | }
142 |
143 | void tab(size_t count)
144 | {
145 | for (size_t i = 0; i < count; i++)
146 | {
147 | file << "\t";
148 | }
149 | }
150 |
151 | void forwardDeclare(std::string name, std::string type = "struct")
152 | {
153 | file << type << " " << name << ";\n";
154 | }
155 |
156 | void pragma(std::string expr)
157 | {
158 | file << "#pragma " << expr << "\n"
159 | << std::endl;
160 | }
161 |
162 | void include(std::string fileName, bool useQuotes = true)
163 | {
164 | if (useQuotes)
165 | file << "#include \"" << fileName << "\"" << std::endl;
166 | else
167 | file << "#include <" << fileName << ">" << std::endl;
168 | }
169 |
170 | void namespaceStart(std::string name)
171 | {
172 | file << "namespace " << name << "\n{" << std::endl;
173 | isInNamespace = true;
174 | }
175 |
176 | void namespaceEnd()
177 | {
178 | if (isInNamespace)
179 | {
180 | file << "}\n"
181 | << std::endl;
182 | isInNamespace = false;
183 | }
184 | }
185 |
186 | void classStart(std::string name, std::string parent)
187 | {
188 | generatedClasses.push_back(name);
189 |
190 | if (isInNamespace)
191 | tab(1);
192 |
193 | file << "class " << name;
194 |
195 | if (!parent.empty())
196 | file << " : public " << parent;
197 |
198 | file << "\n";
199 |
200 | if (isInNamespace)
201 | tab(1);
202 |
203 | file << "{" << std::endl;
204 | isInClass = true;
205 | }
206 |
207 | void definePublic()
208 | {
209 | if (isInClass)
210 | {
211 | file << "public:" << std::endl;
212 | }
213 | }
214 |
215 | void definePrivate()
216 | {
217 | if (isInClass)
218 | {
219 | file << "private:" << std::endl;
220 | }
221 | }
222 |
223 | void classEnd()
224 | {
225 | if (isInClass)
226 | {
227 | if (isInNamespace)
228 | tab(1);
229 |
230 | file << "};\n"
231 | << std::endl;
232 | isInClass = false;
233 | }
234 | }
235 |
236 | void structStart(std::string name, std::string parent = "")
237 | {
238 | generatedStructs.push_back(name);
239 |
240 | if (isInClass)
241 | tab(1);
242 |
243 | if (isInNamespace)
244 | tab(1);
245 |
246 | file << "struct " << name;
247 |
248 | if (!parent.empty())
249 | file << " : " << parent;
250 |
251 | file << "\n";
252 |
253 | if (isInClass)
254 | tab(1);
255 |
256 | if (isInNamespace)
257 | tab(1);
258 |
259 | file << "{" << std::endl;
260 | isInStruct = true;
261 | }
262 |
263 | void structEnd(bool flushQueue = true)
264 | {
265 | if (isInStruct)
266 | {
267 | if (isInClass)
268 | tab(1);
269 |
270 | if (isInNamespace)
271 | tab(1);
272 |
273 | file << "};\n"
274 | << std::endl;
275 | isInStruct = false;
276 | }
277 |
278 | if (flushQueue)
279 | flushStructs();
280 | }
281 |
282 | void variable(Variable& var)
283 | {
284 | if (isInStruct)
285 | tab(1);
286 |
287 | if (isInClass)
288 | tab(1);
289 |
290 | if (isInNamespace)
291 | tab(1);
292 |
293 | if (var.isConstexpr)
294 | file << "constexpr ";
295 |
296 | if (var.isConst)
297 | file << "const ";
298 |
299 | if (var.isStatic)
300 | file << "static ";
301 |
302 | if (var.isStruct)
303 | file << "struct ";
304 |
305 | file << var.type;
306 |
307 | if (var.isPtr)
308 | file << "*";
309 |
310 | if (var.isRef)
311 | file << "&";
312 |
313 | file << " " << var.name
314 | << (var.isArray ? std::format("[0x{:x}]", var.arraySize) : "")
315 | << (var.isBitField ? std::format(": {}", var.bitFieldSize) : "")
316 | << "; "
317 | << (var.comment.empty() ? "" : "// " + var.comment)
318 | << std::endl;
319 | }
320 | };
321 | }
322 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot/
39 |
40 | # Visual Studio 2017 auto generated files
41 | Generated\ Files/
42 |
43 | # MSTest test Results
44 | [Tt]est[Rr]esult*/
45 | [Bb]uild[Ll]og.*
46 |
47 | # NUnit
48 | *.VisualState.xml
49 | TestResult.xml
50 | nunit-*.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS/
54 | [Rr]eleasePS/
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts/
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts/
64 |
65 | # ASP.NET Scaffolding
66 | ScaffoldingReadMe.txt
67 |
68 | # StyleCop
69 | StyleCopReport.xml
70 |
71 | # Files built by Visual Studio
72 | *_i.c
73 | *_p.c
74 | *_h.h
75 | *.ilk
76 | *.meta
77 | *.obj
78 | *.iobj
79 | *.pch
80 | *.pdb
81 | *.ipdb
82 | *.pgc
83 | *.pgd
84 | *.rsp
85 | *.sbr
86 | *.tlb
87 | *.tli
88 | *.tlh
89 | *.tmp
90 | *.tmp_proj
91 | *_wpftmp.csproj
92 | *.log
93 | *.tlog
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
298 | *.vbp
299 |
300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
301 | *.dsw
302 | *.dsp
303 |
304 | # Visual Studio 6 technical files
305 | *.ncb
306 | *.aps
307 |
308 | # Visual Studio LightSwitch build output
309 | **/*.HTMLClient/GeneratedArtifacts
310 | **/*.DesktopClient/GeneratedArtifacts
311 | **/*.DesktopClient/ModelManifest.xml
312 | **/*.Server/GeneratedArtifacts
313 | **/*.Server/ModelManifest.xml
314 | _Pvt_Extensions
315 |
316 | # Paket dependency manager
317 | .paket/paket.exe
318 | paket-files/
319 |
320 | # FAKE - F# Make
321 | .fake/
322 |
323 | # CodeRush personal settings
324 | .cr/personal
325 |
326 | # Python Tools for Visual Studio (PTVS)
327 | __pycache__/
328 | *.pyc
329 |
330 | # Cake - Uncomment if you are using it
331 | # tools/**
332 | # !tools/packages.config
333 |
334 | # Tabs Studio
335 | *.tss
336 |
337 | # Telerik's JustMock configuration file
338 | *.jmconfig
339 |
340 | # BizTalk build output
341 | *.btp.cs
342 | *.btm.cs
343 | *.odx.cs
344 | *.xsd.cs
345 |
346 | # OpenCover UI analysis results
347 | OpenCover/
348 |
349 | # Azure Stream Analytics local run output
350 | ASALocalRun/
351 |
352 | # MSBuild Binary and Structured Log
353 | *.binlog
354 |
355 | # NVidia Nsight GPU debugger configuration file
356 | *.nvuser
357 |
358 | # MFractors (Xamarin productivity tool) working folder
359 | .mfractor/
360 |
361 | # Local History for Visual Studio
362 | .localhistory/
363 |
364 | # Visual Studio History (VSHistory) files
365 | .vshistory/
366 |
367 | # BeatPulse healthcheck temp database
368 | healthchecksdb
369 |
370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
371 | MigrationBackup/
372 |
373 | # Ionide (cross platform F# VS Code tools) working folder
374 | .ionide/
375 |
376 | # Fody - auto-generated XML schema
377 | FodyWeavers.xsd
378 |
379 | # VS Code files for those working on multiple tools
380 | .vscode/*
381 | !.vscode/settings.json
382 | !.vscode/tasks.json
383 | !.vscode/launch.json
384 | !.vscode/extensions.json
385 | *.code-workspace
386 |
387 | # Local History for Visual Studio Code
388 | .history/
389 |
390 | # Windows Installer files from build outputs
391 | *.cab
392 | *.msi
393 | *.msix
394 | *.msm
395 | *.msp
396 |
397 | # JetBrains Rider
398 | *.sln.iml
399 |
--------------------------------------------------------------------------------
/FortKitInsider/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot/
39 |
40 | # Visual Studio 2017 auto generated files
41 | Generated\ Files/
42 |
43 | # MSTest test Results
44 | [Tt]est[Rr]esult*/
45 | [Bb]uild[Ll]og.*
46 |
47 | # NUnit
48 | *.VisualState.xml
49 | TestResult.xml
50 | nunit-*.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS/
54 | [Rr]eleasePS/
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts/
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts/
64 |
65 | # ASP.NET Scaffolding
66 | ScaffoldingReadMe.txt
67 |
68 | # StyleCop
69 | StyleCopReport.xml
70 |
71 | # Files built by Visual Studio
72 | *_i.c
73 | *_p.c
74 | *_h.h
75 | *.ilk
76 | *.meta
77 | *.obj
78 | *.iobj
79 | *.pch
80 | *.pdb
81 | *.ipdb
82 | *.pgc
83 | *.pgd
84 | *.rsp
85 | *.sbr
86 | *.tlb
87 | *.tli
88 | *.tlh
89 | *.tmp
90 | *.tmp_proj
91 | *_wpftmp.csproj
92 | *.log
93 | *.tlog
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
298 | *.vbp
299 |
300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
301 | *.dsw
302 | *.dsp
303 |
304 | # Visual Studio 6 technical files
305 | *.ncb
306 | *.aps
307 |
308 | # Visual Studio LightSwitch build output
309 | **/*.HTMLClient/GeneratedArtifacts
310 | **/*.DesktopClient/GeneratedArtifacts
311 | **/*.DesktopClient/ModelManifest.xml
312 | **/*.Server/GeneratedArtifacts
313 | **/*.Server/ModelManifest.xml
314 | _Pvt_Extensions
315 |
316 | # Paket dependency manager
317 | .paket/paket.exe
318 | paket-files/
319 |
320 | # FAKE - F# Make
321 | .fake/
322 |
323 | # CodeRush personal settings
324 | .cr/personal
325 |
326 | # Python Tools for Visual Studio (PTVS)
327 | __pycache__/
328 | *.pyc
329 |
330 | # Cake - Uncomment if you are using it
331 | # tools/**
332 | # !tools/packages.config
333 |
334 | # Tabs Studio
335 | *.tss
336 |
337 | # Telerik's JustMock configuration file
338 | *.jmconfig
339 |
340 | # BizTalk build output
341 | *.btp.cs
342 | *.btm.cs
343 | *.odx.cs
344 | *.xsd.cs
345 |
346 | # OpenCover UI analysis results
347 | OpenCover/
348 |
349 | # Azure Stream Analytics local run output
350 | ASALocalRun/
351 |
352 | # MSBuild Binary and Structured Log
353 | *.binlog
354 |
355 | # NVidia Nsight GPU debugger configuration file
356 | *.nvuser
357 |
358 | # MFractors (Xamarin productivity tool) working folder
359 | .mfractor/
360 |
361 | # Local History for Visual Studio
362 | .localhistory/
363 |
364 | # Visual Studio History (VSHistory) files
365 | .vshistory/
366 |
367 | # BeatPulse healthcheck temp database
368 | healthchecksdb
369 |
370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
371 | MigrationBackup/
372 |
373 | # Ionide (cross platform F# VS Code tools) working folder
374 | .ionide/
375 |
376 | # Fody - auto-generated XML schema
377 | FodyWeavers.xsd
378 |
379 | # VS Code files for those working on multiple tools
380 | .vscode/*
381 | !.vscode/settings.json
382 | !.vscode/tasks.json
383 | !.vscode/launch.json
384 | !.vscode/extensions.json
385 | *.code-workspace
386 |
387 | # Local History for Visual Studio Code
388 | .history/
389 |
390 | # Windows Installer files from build outputs
391 | *.cab
392 | *.msi
393 | *.msix
394 | *.msm
395 | *.msp
396 |
397 | # JetBrains Rider
398 | *.sln.iml
399 |
--------------------------------------------------------------------------------
/FortKitInsider/FortKitInsider.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {09849e3e-cc19-40bd-8d25-ded5d5f7f55c}
25 | FortKitInsider
26 | 10.0
27 | FortKitInsider
28 |
29 |
30 |
31 | DynamicLibrary
32 | true
33 | v143
34 | Unicode
35 |
36 |
37 | DynamicLibrary
38 | false
39 | v143
40 | true
41 | Unicode
42 |
43 |
44 | DynamicLibrary
45 | true
46 | v143
47 | Unicode
48 |
49 |
50 | DynamicLibrary
51 | false
52 | v143
53 | true
54 | Unicode
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | true
76 | $(SolutionDir)Bin\
77 | FortKitInsider
78 |
79 |
80 | false
81 | $(SolutionDir)Bin\
82 | FortKitInsider
83 |
84 |
85 | true
86 | $(SolutionDir)Bin\
87 | FortKitInsider
88 |
89 |
90 | false
91 | $(SolutionDir)Bin\
92 | FortKitInsider
93 |
94 |
95 |
96 | Level3
97 | true
98 | WIN32;_DEBUG;FORTKITINSIDER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
99 | true
100 | NotUsing
101 | pch.h
102 | stdcpplatest
103 |
104 |
105 | Windows
106 | true
107 | false
108 |
109 |
110 |
111 |
112 | Level3
113 | true
114 | true
115 | true
116 | WIN32;NDEBUG;FORTKITINSIDER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
117 | true
118 | NotUsing
119 | pch.h
120 | stdcpplatest
121 |
122 |
123 | Windows
124 | true
125 | true
126 | true
127 | false
128 |
129 |
130 |
131 |
132 | Level3
133 | true
134 | _DEBUG;FORTKITINSIDER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
135 | true
136 | NotUsing
137 | pch.h
138 | stdcpplatest
139 |
140 |
141 | Windows
142 | true
143 | false
144 |
145 |
146 |
147 |
148 | Level3
149 | true
150 | true
151 | true
152 | NDEBUG;FORTKITINSIDER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
153 | true
154 | NotUsing
155 | pch.h
156 | stdcpplatest
157 |
158 |
159 | Windows
160 | true
161 | true
162 | true
163 | false
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/FortKitInsider/parallel_hashmap/phmap_dump.h:
--------------------------------------------------------------------------------
1 | #if !defined(phmap_dump_h_guard_)
2 | #define phmap_dump_h_guard_
3 |
4 | // ---------------------------------------------------------------------------
5 | // Copyright (c) 2019, Gregory Popovitch - greg7mdp@gmail.com
6 | //
7 | // providing dump/load/mmap_load
8 | //
9 | // Licensed under the Apache License, Version 2.0 (the "License");
10 | // you may not use this file except in compliance with the License.
11 | // You may obtain a copy of the License at
12 | //
13 | // https://www.apache.org/licenses/LICENSE-2.0
14 | //
15 | // Unless required by applicable law or agreed to in writing, software
16 | // distributed under the License is distributed on an "AS IS" BASIS,
17 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | // See the License for the specific language governing permissions and
19 | // limitations under the License.
20 | // ---------------------------------------------------------------------------
21 |
22 | #include
23 | #include
24 | #include
25 | #include "phmap.h"
26 | namespace phmap
27 | {
28 |
29 | namespace type_traits_internal {
30 |
31 | #if defined(__GLIBCXX__) && __GLIBCXX__ < 20150801
32 | template struct IsTriviallyCopyable : public std::integral_constant {};
33 | #else
34 | template struct IsTriviallyCopyable : public std::is_trivially_copyable {};
35 | #endif
36 |
37 | template
38 | struct IsTriviallyCopyable> {
39 | static constexpr bool value = IsTriviallyCopyable::value && IsTriviallyCopyable::value;
40 | };
41 | }
42 |
43 | namespace priv {
44 |
45 | #if !defined(PHMAP_NON_DETERMINISTIC) && !defined(PHMAP_DISABLE_DUMP)
46 |
47 | // ------------------------------------------------------------------------
48 | // dump/load for raw_hash_set
49 | // ------------------------------------------------------------------------
50 | template
51 | template
52 | bool raw_hash_set::phmap_dump(OutputArchive& ar) const {
53 | static_assert(type_traits_internal::IsTriviallyCopyable::value,
54 | "value_type should be trivially copyable");
55 |
56 | ar.saveBinary(&size_, sizeof(size_t));
57 | ar.saveBinary(&capacity_, sizeof(size_t));
58 | if (size_ == 0)
59 | return true;
60 | ar.saveBinary(ctrl_, sizeof(ctrl_t) * (capacity_ + Group::kWidth + 1));
61 | ar.saveBinary(slots_, sizeof(slot_type) * capacity_);
62 | return true;
63 | }
64 |
65 | template
66 | template
67 | bool raw_hash_set::phmap_load(InputArchive& ar) {
68 | static_assert(type_traits_internal::IsTriviallyCopyable::value,
69 | "value_type should be trivially copyable");
70 | raw_hash_set().swap(*this); // clear any existing content
71 | ar.loadBinary(&size_, sizeof(size_t));
72 | ar.loadBinary(&capacity_, sizeof(size_t));
73 |
74 | if (capacity_) {
75 | // allocate memory for ctrl_ and slots_
76 | initialize_slots(capacity_);
77 | }
78 | if (size_ == 0)
79 | return true;
80 | ar.loadBinary(ctrl_, sizeof(ctrl_t) * (capacity_ + Group::kWidth + 1));
81 | ar.loadBinary(slots_, sizeof(slot_type) * capacity_);
82 | return true;
83 | }
84 |
85 | // ------------------------------------------------------------------------
86 | // dump/load for parallel_hash_set
87 | // ------------------------------------------------------------------------
88 | template class RefSet,
90 | class Mtx_,
91 | class Policy, class Hash, class Eq, class Alloc>
92 | template
93 | bool parallel_hash_set::phmap_dump(OutputArchive& ar) const {
94 | static_assert(type_traits_internal::IsTriviallyCopyable::value,
95 | "value_type should be trivially copyable");
96 |
97 | size_t submap_count = subcnt();
98 | ar.saveBinary(&submap_count, sizeof(size_t));
99 | for (size_t i = 0; i < sets_.size(); ++i) {
100 | auto& inner = sets_[i];
101 | typename Lockable::UniqueLock m(const_cast(inner));
102 | if (!inner.set_.phmap_dump(ar)) {
103 | std::cerr << "Failed to dump submap " << i << std::endl;
104 | return false;
105 | }
106 | }
107 | return true;
108 | }
109 |
110 | template class RefSet,
112 | class Mtx_,
113 | class Policy, class Hash, class Eq, class Alloc>
114 | template
115 | bool parallel_hash_set::phmap_load(InputArchive& ar) {
116 | static_assert(type_traits_internal::IsTriviallyCopyable::value,
117 | "value_type should be trivially copyable");
118 |
119 | size_t submap_count = 0;
120 | ar.loadBinary(&submap_count, sizeof(size_t));
121 | if (submap_count != subcnt()) {
122 | std::cerr << "submap count(" << submap_count << ") != N(" << N << ")" << std::endl;
123 | return false;
124 | }
125 |
126 | for (size_t i = 0; i < submap_count; ++i) {
127 | auto& inner = sets_[i];
128 | typename Lockable::UniqueLock m(const_cast(inner));
129 | if (!inner.set_.phmap_load(ar)) {
130 | std::cerr << "Failed to load submap " << i << std::endl;
131 | return false;
132 | }
133 | }
134 | return true;
135 | }
136 |
137 | #endif // !defined(PHMAP_NON_DETERMINISTIC) && !defined(PHMAP_DISABLE_DUMP)
138 |
139 | } // namespace priv
140 |
141 |
142 |
143 | // ------------------------------------------------------------------------
144 | // BinaryArchive
145 | // File is closed when archive object is destroyed
146 | // ------------------------------------------------------------------------
147 |
148 | // ------------------------------------------------------------------------
149 | // ------------------------------------------------------------------------
150 | class BinaryOutputArchive {
151 | public:
152 | BinaryOutputArchive(const char *file_path) {
153 | ofs_.open(file_path, std::ofstream::out | std::ofstream::trunc | std::ofstream::binary);
154 | }
155 |
156 | bool saveBinary(const void *p, size_t sz) {
157 | ofs_.write(reinterpret_cast(p), sz);
158 | return true;
159 | }
160 |
161 | template
162 | typename std::enable_if::value, bool>::type
163 | saveBinary(const V& v) {
164 | ofs_.write(reinterpret_cast(&v), sizeof(V));
165 | return true;
166 | }
167 |
168 | template
169 | auto saveBinary(const Map& v) -> decltype(v.phmap_dump(*this), bool())
170 | {
171 | return v.phmap_dump(*this);
172 | }
173 |
174 | private:
175 | std::ofstream ofs_;
176 | };
177 |
178 |
179 | class BinaryInputArchive {
180 | public:
181 | BinaryInputArchive(const char * file_path) {
182 | ifs_.open(file_path, std::ofstream::in | std::ofstream::binary);
183 | }
184 |
185 | bool loadBinary(void* p, size_t sz) {
186 | ifs_.read(reinterpret_cast(p), sz);
187 | return true;
188 | }
189 |
190 | template
191 | typename std::enable_if::value, bool>::type
192 | loadBinary(V* v) {
193 | ifs_.read(reinterpret_cast(v), sizeof(V));
194 | return true;
195 | }
196 |
197 | template
198 | auto loadBinary(Map* v) -> decltype(v->phmap_load(*this), bool())
199 | {
200 | return v->phmap_load(*this);
201 | }
202 |
203 | private:
204 | std::ifstream ifs_;
205 | };
206 |
207 | } // namespace phmap
208 |
209 |
210 | #ifdef CEREAL_SIZE_TYPE
211 |
212 | template
213 | using PhmapTrivCopyable = typename phmap::type_traits_internal::IsTriviallyCopyable;
214 |
215 | namespace cereal
216 | {
217 | // Overload Cereal serialization code for phmap::flat_hash_map
218 | // -----------------------------------------------------------
219 | template
220 | void save(typename std::enable_if::value && PhmapTrivCopyable::value, typename cereal::BinaryOutputArchive>::type &ar,
221 | phmap::flat_hash_map const &hmap)
222 | {
223 | hmap.phmap_dump(ar);
224 | }
225 |
226 | template
227 | void load(typename std::enable_if::value && PhmapTrivCopyable::value, typename cereal::BinaryInputArchive>::type &ar,
228 | phmap::flat_hash_map &hmap)
229 | {
230 | hmap.phmap_load(ar);
231 | }
232 |
233 |
234 | // Overload Cereal serialization code for phmap::parallel_flat_hash_map
235 | // --------------------------------------------------------------------
236 | template
237 | void save(typename std::enable_if::value && PhmapTrivCopyable::value, typename cereal::BinaryOutputArchive>::type &ar,
238 | phmap::parallel_flat_hash_map const &hmap)
239 | {
240 | hmap.phmap_dump(ar);
241 | }
242 |
243 | template
244 | void load(typename std::enable_if::value && PhmapTrivCopyable::value, typename cereal::BinaryInputArchive>::type &ar,
245 | phmap::parallel_flat_hash_map &hmap)
246 | {
247 | hmap.phmap_load(ar);
248 | }
249 |
250 | // Overload Cereal serialization code for phmap::flat_hash_set
251 | // -----------------------------------------------------------
252 | template
253 | void save(typename std::enable_if::value, typename cereal::BinaryOutputArchive>::type &ar,
254 | phmap::flat_hash_set const &hset)
255 | {
256 | hset.phmap_dump(ar);
257 | }
258 |
259 | template
260 | void load(typename std::enable_if::value, typename cereal::BinaryInputArchive>::type &ar,
261 | phmap::flat_hash_set &hset)
262 | {
263 | hset.phmap_load(ar);
264 | }
265 |
266 | // Overload Cereal serialization code for phmap::parallel_flat_hash_set
267 | // --------------------------------------------------------------------
268 | template
269 | void save(typename std::enable_if::value, typename cereal::BinaryOutputArchive>::type &ar,
270 | phmap::parallel_flat_hash_set const &hset)
271 | {
272 | hset.phmap_dump(ar);
273 | }
274 |
275 | template
276 | void load(typename std::enable_if::value, typename cereal::BinaryInputArchive>::type &ar,
277 | phmap::parallel_flat_hash_set &hset)
278 | {
279 | hset.phmap_load(ar);
280 | }
281 | }
282 |
283 | #endif
284 |
285 |
286 |
287 |
288 | #endif // phmap_dump_h_guard_
289 |
--------------------------------------------------------------------------------
/FortKitInsider/parallel_hashmap/phmap_utils.h:
--------------------------------------------------------------------------------
1 | #if !defined(phmap_utils_h_guard_)
2 | #define phmap_utils_h_guard_
3 |
4 | // ---------------------------------------------------------------------------
5 | // Copyright (c) 2019, Gregory Popovitch - greg7mdp@gmail.com
6 | //
7 | // minimal header providing phmap::HashState
8 | //
9 | // use as: phmap::HashState().combine(0, _first_name, _last_name, _age);
10 | //
11 | // Licensed under the Apache License, Version 2.0 (the "License");
12 | // you may not use this file except in compliance with the License.
13 | // You may obtain a copy of the License at
14 | //
15 | // https://www.apache.org/licenses/LICENSE-2.0
16 | //
17 | // Unless required by applicable law or agreed to in writing, software
18 | // distributed under the License is distributed on an "AS IS" BASIS,
19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 | // See the License for the specific language governing permissions and
21 | // limitations under the License.
22 | // ---------------------------------------------------------------------------
23 |
24 | #ifdef _MSC_VER
25 | #pragma warning(push)
26 | #pragma warning(disable : 4514) // unreferenced inline function has been removed
27 | #pragma warning(disable : 4710) // function not inlined
28 | #pragma warning(disable : 4711) // selected for automatic inline expansion
29 | #endif
30 |
31 | #include
32 | #include
33 | #include
34 | #include "phmap_bits.h"
35 |
36 | // ---------------------------------------------------------------
37 | // Absl forward declaration requires global scope.
38 | // ---------------------------------------------------------------
39 | #if defined(PHMAP_USE_ABSL_HASH) && !defined(phmap_fwd_decl_h_guard_) && !defined(ABSL_HASH_HASH_H_)
40 | namespace absl { template struct Hash; };
41 | #endif
42 |
43 | namespace phmap
44 | {
45 |
46 | // ---------------------------------------------------------------
47 | // ---------------------------------------------------------------
48 | template
49 | struct phmap_mix
50 | {
51 | inline size_t operator()(size_t) const;
52 | };
53 |
54 | template<>
55 | struct phmap_mix<4>
56 | {
57 | inline size_t operator()(size_t a) const
58 | {
59 | static constexpr uint64_t kmul = 0xcc9e2d51UL;
60 | // static constexpr uint64_t kmul = 0x3B9ACB93UL; // [greg] my own random prime
61 | uint64_t l = a * kmul;
62 | return static_cast(l ^ (l >> 32));
63 | }
64 | };
65 |
66 | #if defined(PHMAP_HAS_UMUL128)
67 | template<>
68 | struct phmap_mix<8>
69 | {
70 | // Very fast mixing (similar to Abseil)
71 | inline size_t operator()(size_t a) const
72 | {
73 | static constexpr uint64_t k = 0xde5fb9d2630458e9ULL;
74 | // static constexpr uint64_t k = 0x7C9D0BF0567102A5ULL; // [greg] my own random prime
75 | uint64_t h;
76 | uint64_t l = umul128(a, k, &h);
77 | return static_cast(h + l);
78 | }
79 | };
80 | #else
81 | template<>
82 | struct phmap_mix<8>
83 | {
84 | inline size_t operator()(size_t a) const
85 | {
86 | a = (~a) + (a << 21); // a = (a << 21) - a - 1;
87 | a = a ^ (a >> 24);
88 | a = (a + (a << 3)) + (a << 8); // a * 265
89 | a = a ^ (a >> 14);
90 | a = (a + (a << 2)) + (a << 4); // a * 21
91 | a = a ^ (a >> 28);
92 | a = a + (a << 31);
93 | return static_cast(a);
94 | }
95 | };
96 | #endif
97 |
98 | // --------------------------------------------
99 | template
100 | struct fold_if_needed
101 | {
102 | inline size_t operator()(uint64_t) const;
103 | };
104 |
105 | template<>
106 | struct fold_if_needed<4>
107 | {
108 | inline size_t operator()(uint64_t a) const
109 | {
110 | return static_cast(a ^ (a >> 32));
111 | }
112 | };
113 |
114 | template<>
115 | struct fold_if_needed<8>
116 | {
117 | inline size_t operator()(uint64_t a) const
118 | {
119 | return static_cast(a);
120 | }
121 | };
122 |
123 | // ---------------------------------------------------------------
124 | // see if class T has a hash_value() friend method
125 | // ---------------------------------------------------------------
126 | template
127 | struct has_hash_value
128 | {
129 | private:
130 | typedef std::true_type yes;
131 | typedef std::false_type no;
132 |
133 | template static auto test(int) -> decltype(hash_value(std::declval()) == 1, yes());
134 |
135 | template static no test(...);
136 |
137 | public:
138 | static constexpr bool value = std::is_same(0)), yes>::value;
139 | };
140 |
141 | #if defined(PHMAP_USE_ABSL_HASH) && !defined(phmap_fwd_decl_h_guard_)
142 | template using Hash = ::absl::Hash;
143 | #elif !defined(PHMAP_USE_ABSL_HASH)
144 | // ---------------------------------------------------------------
145 | // phmap::Hash
146 | // ---------------------------------------------------------------
147 | template
148 | struct Hash
149 | {
150 | template ::value, int>::type = 0>
151 | size_t _hash(const T& val) const
152 | {
153 | return hash_value(val);
154 | }
155 |
156 | template ::value, int>::type = 0>
157 | size_t _hash(const T& val) const
158 | {
159 | return std::hash()(val);
160 | }
161 |
162 | inline size_t operator()(const T& val) const
163 | {
164 | return _hash(val);
165 | }
166 | };
167 |
168 | template
169 | struct phmap_unary_function
170 | {
171 | typedef ArgumentType argument_type;
172 | typedef ResultType result_type;
173 | };
174 |
175 | template <>
176 | struct Hash : public phmap_unary_function
177 | {
178 | inline size_t operator()(bool val) const noexcept
179 | { return static_cast(val); }
180 | };
181 |
182 | template <>
183 | struct Hash : public phmap_unary_function
184 | {
185 | inline size_t operator()(char val) const noexcept
186 | { return static_cast(val); }
187 | };
188 |
189 | template <>
190 | struct Hash