├── .clang-format ├── .gitignore ├── .vscode └── settings.json ├── FortKit.sln ├── FortKitInsider ├── .clang-format ├── .gitignore ├── FortKitInsider.vcxproj ├── FortKitInsider.vcxproj.filters ├── FortKitInsider.vcxproj.user ├── consts.h ├── cppgenerator.h ├── dllmain.cpp ├── dumper.h ├── enums.h ├── exceptions.h ├── framework.h ├── generic.h ├── memcury.h ├── parallel_hashmap │ ├── btree.h │ ├── conanfile.py │ ├── meminfo.h │ ├── phmap.h │ ├── phmap_base.h │ ├── phmap_bits.h │ ├── phmap_config.h │ ├── phmap_dump.h │ ├── phmap_fwd_decl.h │ └── phmap_utils.h ├── ue4.cpp ├── ue4.h ├── usmap.h ├── util.h └── writer.h └── README.md /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: WebKit 3 | AlignAfterOpenBracket: DontAlign 4 | BreakBeforeBraces: Allman 5 | NamespaceIndentation: All 6 | SortIncludes: false 7 | 8 | ... 9 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "xstring": "cpp" 4 | } 5 | } -------------------------------------------------------------------------------- /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/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: WebKit 3 | AlignAfterOpenBracket: DontAlign 4 | BreakBeforeBraces: Allman 5 | NamespaceIndentation: All 6 | SortIncludes: false 7 | 8 | ... 9 | -------------------------------------------------------------------------------- /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/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/FortKitInsider.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/dumper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "generic.h" 3 | #include "ue4.h" 4 | #include "util.h" 5 | #include "usmap.h" 6 | 7 | #include "cppgenerator.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | uintptr_t ModuleBase = reinterpret_cast(GetModuleHandle(nullptr)); 15 | 16 | namespace Dumper 17 | { 18 | static void DumpNames() 19 | { 20 | std::ofstream NamesDump("NamesDump.txt"); 21 | 22 | for (size_t i = 0; i < GObjects->NumElements; i++) 23 | { 24 | auto uObj = GObjects->GetByIndex(i); 25 | 26 | if (Util::IsBadReadPtr(uObj)) 27 | continue; 28 | 29 | NamesDump << '[' << uObj->InternalIndex << "] " << uObj->GetFullName() << '\n'; 30 | } 31 | 32 | NamesDump.close(); 33 | } 34 | 35 | static auto GeneratePadding(CPPGenerator::Header& file, const int& size, const int& offset, const std::string& comment, const std::string& name = "unreflected") 36 | { 37 | auto var = CPPGenerator::Variable::New(std::format("{}_{:x}", name, offset)); 38 | var.isArray = true; 39 | var.arraySize = size; 40 | 41 | var.comment = std::format("0x{:x} (0x{:x}) {}", offset, size, comment); 42 | 43 | return file.variable(var); 44 | } 45 | 46 | static auto GenerateBitPadding(CPPGenerator::Header& file, const int& size, const int& id, const int& offset, const std::string& name = "unreflectedBit") 47 | { 48 | auto var = CPPGenerator::Variable::New(std::format("{}_{:x}", name, id)); 49 | 50 | var.isBitField = true; 51 | var.bitFieldSize = size; 52 | var.comment = std::format("0x{:x} (0x{:x})", offset, size); 53 | 54 | return file.variable(var); 55 | } 56 | 57 | static void GenerateFields(CPPGenerator::Header& file, UStruct* Struct) 58 | { 59 | auto prop = (FProperty*)Struct->ChildProperties; 60 | 61 | if (Struct->PropertiesSize > 0x0 && !Struct->ChildProperties && Util::IsBadReadPtr(Struct->ChildProperties)) 62 | { 63 | auto var = CPPGenerator::Variable::New(std::format("unreflected_{:x}", Struct->PropertiesSize)); 64 | var.isArray = true; 65 | var.arraySize = Struct->PropertiesSize; 66 | 67 | return file.variable(var); 68 | } 69 | 70 | auto offset = prop->Offset_Internal + prop->ElementSize * prop->ArrayDim; 71 | 72 | if (Struct->SuperStruct->IsValid() && prop->Offset_Internal >= Struct->SuperStruct->PropertiesSize) 73 | { 74 | offset = Struct->SuperStruct->PropertiesSize; 75 | } 76 | 77 | auto bitFieldsCount = 0; 78 | FBoolProperty* lastBoolProp = nullptr; 79 | 80 | while (prop) 81 | { 82 | if (offset < prop->Offset_Internal) 83 | { 84 | lastBoolProp = nullptr; 85 | GeneratePadding(file, prop->Offset_Internal - offset, offset, ""); 86 | } 87 | 88 | std::string comment; 89 | auto propName = prop->GetName(); 90 | Util::FixName(propName); 91 | 92 | auto cppType = Generic::StringifyPropType(prop); 93 | 94 | if (!cppType.empty()) 95 | { 96 | auto var = CPPGenerator::Variable::New(cppType, propName); 97 | 98 | if (lastBoolProp && prop->ClassPrivate->Id == FFieldClassID::Bool && reinterpret_cast(prop)->IsBitfield()) 99 | { 100 | auto bprop = reinterpret_cast(prop); 101 | auto missingBits = bprop->GetMissingBitsCount(lastBoolProp); 102 | 103 | if (missingBits.second != -1) 104 | { 105 | if (missingBits.first > 0) 106 | { 107 | GenerateBitPadding(file, missingBits.first, bitFieldsCount++, lastBoolProp->Offset_Internal); 108 | } 109 | 110 | if (missingBits.second > 0) 111 | { 112 | GenerateBitPadding(file, missingBits.second, bitFieldsCount++, prop->Offset_Internal); 113 | } 114 | } 115 | else if (missingBits.first > 0) 116 | { 117 | GenerateBitPadding(file, missingBits.first, bitFieldsCount++, prop->Offset_Internal); 118 | } 119 | 120 | lastBoolProp = bprop; 121 | 122 | var.isBitField = true; 123 | var.bitFieldSize = 1; 124 | } 125 | else 126 | { 127 | lastBoolProp = nullptr; 128 | } 129 | 130 | comment += std::format("0x{:x} (0x{:x})", prop->Offset_Internal, prop->ElementSize); 131 | 132 | if (prop->ArrayDim > 1) 133 | { 134 | var.isArray = true; 135 | var.arraySize = prop->ArrayDim; 136 | comment += " (ARRAY) "; 137 | } 138 | 139 | var.comment = comment; 140 | file.variable(var); 141 | } 142 | else 143 | { 144 | // those are ignored on purpose 145 | if (prop->ClassPrivate->Id != FFieldClassID::MulticastInlineDelegate && prop->ClassPrivate->Id != FFieldClassID::Delegate) 146 | { 147 | comment += "(UNHANDLED PROPERTY TYPE: " + prop->ClassPrivate->Name.ToString() + " UID: " + std::to_string((int)prop->ClassPrivate->Id) + ")"; 148 | } 149 | 150 | GeneratePadding(file, prop->ElementSize, prop->Offset_Internal, comment, propName); 151 | } 152 | 153 | offset = prop->Offset_Internal + prop->ElementSize * prop->ArrayDim; 154 | prop = (FProperty*)prop->Next; 155 | } 156 | 157 | if (offset < Struct->PropertiesSize) 158 | { 159 | auto var = CPPGenerator::Variable::New(std::format("padding_{:x}", offset)); 160 | var.isArray = true; 161 | var.arraySize = Struct->PropertiesSize - offset; 162 | var.comment = std::format("0x{:x} (0x{:x})", offset, Struct->PropertiesSize - offset); 163 | 164 | file.variable(var); 165 | } 166 | } 167 | 168 | static void GenerateFunctions(CPPGenerator::Header& file, UClass* Struct) 169 | { 170 | auto child = Struct->Children; 171 | 172 | if (!child || Util::IsBadReadPtr(child)) 173 | { 174 | return; 175 | } 176 | 177 | // std::vector nativeFunctions; 178 | 179 | // if (Struct->NativeFunctionLookupTable.Num() > 0) 180 | // { 181 | // nativeFunctions = Struct->NativeFunctionLookupTable.ToVector(); 182 | // } 183 | 184 | file.AddText("\n\t/* Functions */\n"); 185 | 186 | std::string params; 187 | 188 | while (child) 189 | { 190 | if (child->IsA(UFunction::StaticClass())) 191 | { 192 | auto function = child->Cast(); 193 | 194 | std::string retType; 195 | std::string functionSig; 196 | 197 | retType = "void"; 198 | 199 | auto paramChild = (FProperty*)function->ChildProperties; 200 | 201 | while (paramChild) 202 | { 203 | auto paramType = Generic::StringifyPropType(paramChild); 204 | 205 | if (paramChild->PropertyFlags & CPF_ReturnParm) 206 | { 207 | if (!paramType.empty()) 208 | { 209 | retType = paramType; 210 | } 211 | 212 | break; 213 | } 214 | 215 | if (!paramType.empty()) 216 | { 217 | if (reinterpret_cast(child)->ArrayDim <= 1) 218 | { 219 | paramType += "&"; 220 | } 221 | } 222 | else 223 | { 224 | break; 225 | } 226 | 227 | auto paramName = paramChild->GetName(); 228 | Util::FixName(paramName); 229 | 230 | functionSig += paramType + " " + paramName; 231 | params += paramName; 232 | 233 | paramChild = (FProperty*)paramChild->Next; 234 | 235 | if (paramChild && !(paramChild->PropertyFlags & CPF_ReturnParm)) 236 | functionSig += ", "; 237 | params += ", "; 238 | } 239 | 240 | auto name = function->GetName(); 241 | Util::FixName(name); 242 | 243 | /* auto nativeFunctionLookup = std::find_if(nativeFunctions.begin(), nativeFunctions.end(), 244 | [&](const FNativeFunctionLookup& lookup) 245 | { 246 | return lookup.Name.ToString().starts_with(function->GetName()); 247 | }); 248 | 249 | std::string nativeFuncComment = " (Has no native function)"; 250 | 251 | if (nativeFunctionLookup != std::end(nativeFunctions)) 252 | { 253 | nativeFuncComment = std::format(" (Underlying native function: {} 0x{:x})", nativeFunctionLookup->Name.ToString(), (uintptr_t)nativeFunctionLookup->Pointer - ModuleBase); 254 | nativeFunctions.erase(nativeFunctionLookup); 255 | } 256 | 257 | file.AddText(std::format("\n\t// {}{}\n", function->GetFullName(), nativeFuncComment));*/ 258 | 259 | file.AddText(std::format("\t{}{} {}({}); // {}\n", (function->FunctionFlags & FUNC_Static ? "static " : ""), retType, name, functionSig, Generic::StringifyFlags(function->FunctionFlags))); 260 | 261 | params.clear(); 262 | } 263 | 264 | child = child->Next; 265 | } 266 | 267 | // if (nativeFunctions.size() > 0) 268 | // { 269 | // file.AddText("\n\t/* Unreflected Native Functions */\n"); 270 | 271 | // for (auto&& lookup : nativeFunctions) 272 | // { 273 | // file.AddText(std::format("\t// Function: {} 0x{:x}\n", lookup.Name.ToString(), (uintptr_t)lookup.Pointer - ModuleBase)); 274 | // } 275 | // } 276 | } 277 | 278 | phmap::flat_hash_map names; 279 | 280 | static void DumpStruct(UStruct* Struct) 281 | { 282 | if (!Struct->ChildProperties && Util::IsBadReadPtr(Struct->ChildProperties) && Struct->PropertiesSize == 0x0) 283 | return; 284 | 285 | auto cppname = Struct->GetCPPName(); 286 | 287 | CPPGenerator::Header file("DUMP\\" + cppname + (names.contains(cppname) ? "_" + std::to_string(names[cppname]) : "")); 288 | names[cppname] += 1; 289 | 290 | auto isClass = Struct->IsA(UClass::StaticClass()); 291 | 292 | file.AddText(std::format("// {}\n", Struct->GetFullName())); 293 | file.AddText(std::format("// Size: 0x{:x}\n", Struct->PropertiesSize)); 294 | 295 | auto name = Struct->GetCPPName(); 296 | auto parent = Struct->SuperStruct ? Struct->SuperStruct->GetCPPName() : ""; 297 | 298 | isClass ? file.classStart(name, parent) : file.structStart(name, parent); 299 | 300 | if (Struct->SuperStruct) 301 | { 302 | if (Struct->PropertiesSize > Struct->SuperStruct->PropertiesSize) 303 | { 304 | GenerateFields(file, Struct); 305 | } 306 | } 307 | else 308 | GenerateFields(file, Struct); 309 | 310 | if (isClass) 311 | { 312 | GenerateFunctions(file, (UClass*)Struct); 313 | } 314 | 315 | isClass ? file.classEnd() : file.structEnd(); 316 | } 317 | 318 | static void DumpEnum(UEnum* Enum) 319 | { 320 | if (!Enum->CppType.IsValid() && Util::IsBadReadPtr((void*)Enum->CppType.ToWString())) 321 | { 322 | return; 323 | } 324 | 325 | auto cppname = Enum->GetCPPString(); 326 | 327 | auto fileType = ".h"; 328 | auto fileName = "DUMP\\" + cppname + (names.contains(cppname) ? "_" + std::to_string(names[cppname]) : "") + fileType; // UObject::GetName can be used too but this is good 329 | names[cppname] += 1; 330 | 331 | std::ofstream file(fileName); 332 | file << "// " << Enum->GetFullName() << std::endl; 333 | file << "enum class " << Enum->GetCPPString() << " : " << Enum->GetEnumType() << std::endl 334 | << "{\n"; 335 | 336 | for (int i = 0; i < Enum->Names.Num(); i++) 337 | { 338 | auto name = Enum->Names[i].Key.ToString(); 339 | auto find = name.find(':'); 340 | 341 | if (find != std::string::npos) 342 | name = name.substr(find + 2); 343 | 344 | file << " " << name << " = " << std::to_string(Enum->Names[i].Value); 345 | 346 | if (i < (Enum->Names.Num() - 1)) 347 | { 348 | file << ','; 349 | } 350 | 351 | file << std::endl; 352 | } 353 | 354 | file << "};"; 355 | } 356 | 357 | static void Dump() 358 | { 359 | printf("[=] Dumping.\n"); 360 | 361 | std::filesystem::create_directories("DUMP"); 362 | 363 | auto Start = std::chrono::steady_clock::now(); 364 | 365 | auto dumped = 0; 366 | auto enumsDumped = 0; 367 | for (auto i = 0x0; i < GObjects->NumElements; ++i) 368 | { 369 | auto object = GObjects->GetByIndex(i); 370 | if (object == nullptr) 371 | { 372 | continue; 373 | } 374 | 375 | if (object->IsA(UStruct::StaticClass())) 376 | { 377 | if (object->Class == UFunction::StaticClass()) 378 | continue; 379 | 380 | DumpStruct((UStruct*)object); 381 | dumped++; 382 | } 383 | else if (object->IsA(UEnum::StaticClass())) 384 | { 385 | DumpEnum((UEnum*)object); 386 | enumsDumped++; 387 | } 388 | } 389 | 390 | auto End = std::chrono::steady_clock::now(); 391 | printf("[+] Dumping done in %.02f ms\n", (End - Start).count() / 1000000.); 392 | 393 | MessageBoxA(nullptr, ("Dumped " + std::to_string(dumped) + " UStruct(s) and " + std::to_string(enumsDumped) + " UEnum(s)").c_str(), "Done!", MB_OK); 394 | } 395 | 396 | static void GenerateUsmap() 397 | { 398 | printf("[=] Generating Usmap.\n"); 399 | 400 | auto Start = std::chrono::steady_clock::now(); 401 | 402 | Usmap().Generate(); 403 | 404 | auto End = std::chrono::steady_clock::now(); 405 | 406 | printf("[+] Usmap file generated in %.02f ms\n", (End - Start).count() / 1000000.); 407 | } 408 | } 409 | -------------------------------------------------------------------------------- /FortKitInsider/enums.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "framework.h" 3 | 4 | enum class EEnumFlags 5 | { 6 | None, 7 | Flags = 0x00000001, 8 | NewerVersionExists = 0x00000002, 9 | }; 10 | 11 | enum ASM : DWORD 12 | { 13 | JMP_REL8 = 0xEB, 14 | CALL = 0xE8, 15 | LEA = 0x8D, 16 | CDQ = 0x99, 17 | CMOVL = 0x4C, 18 | CMOVS = 0x48, 19 | INT3 = 0xCC, 20 | RETN = 0xC3, 21 | SKIP 22 | }; 23 | 24 | enum DumpType : uint32_t 25 | { 26 | FunctionParamsHeaders, 27 | 28 | }; 29 | 30 | enum ELifetimeCondition 31 | { 32 | COND_None = 0, 33 | COND_InitialOnly = 1, 34 | COND_OwnerOnly = 2, 35 | COND_SkipOwner = 3, 36 | COND_SimulatedOnly = 4, 37 | COND_AutonomousOnly = 5, 38 | COND_SimulatedOrPhysics = 6, 39 | COND_InitialOrOwner = 7, 40 | COND_Custom = 8, 41 | COND_ReplayOrOwner = 9, 42 | COND_ReplayOnly = 10, 43 | COND_SimulatedOnlyNoReplay = 11, 44 | COND_SimulatedOrPhysicsNoReplay = 12, 45 | COND_SkipReplay = 13, 46 | COND_Never = 15, 47 | COND_Max = 16, 48 | }; 49 | 50 | enum EObjectFlags : uint32_t 51 | { 52 | RF_NoFlags = 0x00000000, 53 | RF_Public = 0x00000001, 54 | RF_Standalone = 0x00000002, 55 | RF_MarkAsNative = 0x00000004, 56 | RF_Transactional = 0x00000008, 57 | RF_ClassDefaultObject = 0x00000010, 58 | RF_ArchetypeObject = 0x00000020, 59 | RF_Transient = 0x00000040, 60 | RF_MarkAsRootSet = 0x00000080, 61 | RF_TagGarbageTemp = 0x00000100, 62 | RF_NeedInitialization = 0x00000200, 63 | RF_NeedLoad = 0x00000400, 64 | RF_KeepForCooker = 0x00000800, 65 | RF_NeedPostLoad = 0x00001000, 66 | RF_NeedPostLoadSubobjects = 0x00002000, 67 | RF_NewerVersionExists = 0x00004000, 68 | RF_BeginDestroyed = 0x00008000, 69 | RF_FinishDestroyed = 0x00010000, 70 | RF_BeingRegenerated = 0x00020000, 71 | RF_DefaultSubObject = 0x00040000, 72 | RF_WasLoaded = 0x00080000, 73 | RF_TextExportTransient = 0x00100000, 74 | RF_LoadCompleted = 0x00200000, 75 | RF_InheritableComponentTemplate = 0x00400000, 76 | RF_DuplicateTransient = 0x00800000, 77 | RF_StrongRefOnFrame = 0x01000000, 78 | RF_NonPIEDuplicateTransient = 0x02000000, 79 | RF_Dynamic = 0x04000000, 80 | RF_WillBeLoaded = 0x08000000, 81 | }; 82 | 83 | enum EPropertyFlags : uint64_t 84 | { 85 | CPF_None = 0, 86 | 87 | CPF_Edit = 0x0000000000000001, ///< Property is user-settable in the editor. 88 | CPF_ConstParm = 0x0000000000000002, ///< This is a constant function parameter 89 | CPF_BlueprintVisible = 0x0000000000000004, ///< This property can be read by blueprint code 90 | CPF_ExportObject = 0x0000000000000008, ///< Object can be exported with actor. 91 | CPF_BlueprintReadOnly = 0x0000000000000010, ///< This property cannot be modified by blueprint code 92 | CPF_Net = 0x0000000000000020, ///< Property is relevant to network replication. 93 | CPF_EditFixedSize = 0x0000000000000040, ///< Indicates that elements of an array can be modified, but its size cannot be changed. 94 | CPF_Parm = 0x0000000000000080, ///< Function/When call parameter. 95 | CPF_OutParm = 0x0000000000000100, ///< Value is copied out after function call. 96 | CPF_ZeroConstructor = 0x0000000000000200, ///< memset is fine for construction 97 | CPF_ReturnParm = 0x0000000000000400, ///< Return value. 98 | CPF_DisableEditOnTemplate = 0x0000000000000800, ///< Disable editing of this property on an archetype/sub-blueprint 99 | //CPF_ = 0x0000000000001000, ///< 100 | CPF_Transient = 0x0000000000002000, ///< Property is transient: shouldn't be saved or loaded, except for Blueprint CDOs. 101 | CPF_Config = 0x0000000000004000, ///< Property should be loaded/saved as permanent profile. 102 | //CPF_ = 0x0000000000008000, ///< 103 | CPF_DisableEditOnInstance = 0x0000000000010000, ///< Disable editing on an instance of this class 104 | CPF_EditConst = 0x0000000000020000, ///< Property is uneditable in the editor. 105 | CPF_GlobalConfig = 0x0000000000040000, ///< Load config from base class, not subclass. 106 | CPF_InstancedReference = 0x0000000000080000, ///< Property is a component references. 107 | //CPF_ = 0x0000000000100000, ///< 108 | CPF_DuplicateTransient = 0x0000000000200000, ///< Property should always be reset to the default value during any type of duplication (copy/paste, binary duplication, etc.) 109 | //CPF_ = 0x0000000000400000, ///< 110 | //CPF_ = 0x0000000000800000, ///< 111 | CPF_SaveGame = 0x0000000001000000, ///< Property should be serialized for save games, this is only checked for game-specific archives with ArIsSaveGame 112 | CPF_NoClear = 0x0000000002000000, ///< Hide clear (and browse) button. 113 | //CPF_ = 0x0000000004000000, ///< 114 | CPF_ReferenceParm = 0x0000000008000000, ///< Value is passed by reference; CPF_OutParam and CPF_Param should also be set. 115 | CPF_BlueprintAssignable = 0x0000000010000000, ///< MC Delegates only. Property should be exposed for assigning in blueprint code 116 | CPF_Deprecated = 0x0000000020000000, ///< Property is deprecated. Read it from an archive, but don't save it. 117 | CPF_IsPlainOldData = 0x0000000040000000, ///< If this is set, then the property can be memcopied instead of CopyCompleteValue / CopySingleValue 118 | CPF_RepSkip = 0x0000000080000000, ///< Not replicated. For non replicated properties in replicated structs 119 | CPF_RepNotify = 0x0000000100000000, ///< Notify actors when a property is replicated 120 | CPF_Interp = 0x0000000200000000, ///< interpolatable property for use with cinematics 121 | CPF_NonTransactional = 0x0000000400000000, ///< Property isn't transacted 122 | CPF_EditorOnly = 0x0000000800000000, ///< Property should only be loaded in the editor 123 | CPF_NoDestructor = 0x0000001000000000, ///< No destructor 124 | //CPF_ = 0x0000002000000000, ///< 125 | CPF_AutoWeak = 0x0000004000000000, ///< Only used for weak pointers, means the export type is autoweak 126 | CPF_ContainsInstancedReference = 0x0000008000000000, ///< Property contains component references. 127 | CPF_AssetRegistrySearchable = 0x0000010000000000, ///< asset instances will add properties with this flag to the asset registry automatically 128 | CPF_SimpleDisplay = 0x0000020000000000, ///< The property is visible by default in the editor details view 129 | CPF_AdvancedDisplay = 0x0000040000000000, ///< The property is advanced and not visible by default in the editor details view 130 | CPF_Protected = 0x0000080000000000, ///< property is protected from the perspective of script 131 | CPF_BlueprintCallable = 0x0000100000000000, ///< MC Delegates only. Property should be exposed for calling in blueprint code 132 | CPF_BlueprintAuthorityOnly = 0x0000200000000000, ///< MC Delegates only. This delegate accepts (only in blueprint) only events with BlueprintAuthorityOnly. 133 | CPF_TextExportTransient = 0x0000400000000000, ///< Property shouldn't be exported to text format (e.g. copy/paste) 134 | CPF_NonPIEDuplicateTransient = 0x0000800000000000, ///< Property should only be copied in PIE 135 | CPF_ExposeOnSpawn = 0x0001000000000000, ///< Property is exposed on spawn 136 | CPF_PersistentInstance = 0x0002000000000000, ///< A object referenced by the property is duplicated like a component. (Each actor should have an own instance.) 137 | CPF_UObjectWrapper = 0x0004000000000000, ///< Property was parsed as a wrapper class like TSubclassOf, FScriptInterface etc., rather than a USomething* 138 | CPF_HasGetValueTypeHash = 0x0008000000000000, ///< This property can generate a meaningful hash value. 139 | CPF_NativeAccessSpecifierPublic = 0x0010000000000000, ///< Public native access specifier 140 | CPF_NativeAccessSpecifierProtected = 0x0020000000000000, ///< Protected native access specifier 141 | CPF_NativeAccessSpecifierPrivate = 0x0040000000000000, ///< Private native access specifier 142 | CPF_SkipSerialization = 0x0080000000000000, ///< Property shouldn't be serialized, can still be exported to text 143 | }; 144 | 145 | 146 | enum EClassFlags 147 | { 148 | /** No Flags */ 149 | CLASS_None = 0x00000000u, 150 | /** Class is abstract and can't be instantiated directly. */ 151 | CLASS_Abstract = 0x00000001u, 152 | /** Save object configuration only to Default INIs, never to local INIs. Must be combined with CLASS_Config */ 153 | CLASS_DefaultConfig = 0x00000002u, 154 | /** Load object configuration at construction time. */ 155 | CLASS_Config = 0x00000004u, 156 | /** This object type can't be saved; null it out at save time. */ 157 | CLASS_Transient = 0x00000008u, 158 | /** Successfully parsed. */ 159 | CLASS_Parsed = 0x00000010u, 160 | /** */ 161 | CLASS_MatchedSerializers = 0x00000020u, 162 | /** Indicates that the config settings for this class will be saved to Project/User*.ini (similar to CLASS_GlobalUserConfig) */ 163 | CLASS_ProjectUserConfig = 0x00000040u, 164 | /** Class is a native class - native interfaces will have CLASS_Native set, but not RF_MarkAsNative */ 165 | CLASS_Native = 0x00000080u, 166 | /** Don't export to C++ header. */ 167 | CLASS_NoExport = 0x00000100u, 168 | /** Do not allow users to create in the editor. */ 169 | CLASS_NotPlaceable = 0x00000200u, 170 | /** Handle object configuration on a per-object basis, rather than per-class. */ 171 | CLASS_PerObjectConfig = 0x00000400u, 172 | 173 | /** Whether SetUpRuntimeReplicationData still needs to be called for this class */ 174 | CLASS_ReplicationDataIsSetUp = 0x00000800u, 175 | 176 | /** Class can be constructed from editinline New button. */ 177 | CLASS_EditInlineNew = 0x00001000u, 178 | /** Display properties in the editor without using categories. */ 179 | CLASS_CollapseCategories = 0x00002000u, 180 | /** Class is an interface **/ 181 | CLASS_Interface = 0x00004000u, 182 | /** Do not export a constructor for this class, assuming it is in the cpptext **/ 183 | CLASS_CustomConstructor = 0x00008000u, 184 | /** all properties and functions in this class are const and should be exported as const */ 185 | CLASS_Const = 0x00010000u, 186 | 187 | /** Class flag indicating the class is having its layout changed, and therefore is not ready for a CDO to be created */ 188 | CLASS_LayoutChanging = 0x00020000u, 189 | 190 | /** Indicates that the class was created from blueprint source material */ 191 | CLASS_CompiledFromBlueprint = 0x00040000u, 192 | 193 | /** Indicates that only the bare minimum bits of this class should be DLL exported/imported */ 194 | CLASS_MinimalAPI = 0x00080000u, 195 | 196 | /** Indicates this class must be DLL exported/imported (along with all of it's members) */ 197 | CLASS_RequiredAPI = 0x00100000u, 198 | 199 | /** Indicates that references to this class default to instanced. Used to be subclasses of UComponent, but now can be any UObject */ 200 | CLASS_DefaultToInstanced = 0x00200000u, 201 | 202 | /** Indicates that the parent token stream has been merged with ours. */ 203 | CLASS_TokenStreamAssembled = 0x00400000u, 204 | /** Class has component properties. */ 205 | CLASS_HasInstancedReference = 0x00800000u, 206 | /** Don't show this class in the editor class browser or edit inline new menus. */ 207 | CLASS_Hidden = 0x01000000u, 208 | /** Don't save objects of this class when serializing */ 209 | CLASS_Deprecated = 0x02000000u, 210 | /** Class not shown in editor drop down for class selection */ 211 | CLASS_HideDropDown = 0x04000000u, 212 | /** Class settings are saved to /..../Blah.ini (as opposed to CLASS_DefaultConfig) */ 213 | CLASS_GlobalUserConfig = 0x08000000u, 214 | /** Class was declared directly in C++ and has no boilerplate generated by UnrealHeaderTool */ 215 | CLASS_Intrinsic = 0x10000000u, 216 | /** Class has already been constructed (maybe in a previous DLL version before hot-reload). */ 217 | CLASS_Constructed = 0x20000000u, 218 | /** Indicates that object configuration will not check against ini base/defaults when serialized */ 219 | CLASS_ConfigDoNotCheckDefaults = 0x40000000u, 220 | /** Class has been consigned to oblivion as part of a blueprint recompile, and a newer version currently exists. */ 221 | CLASS_NewerVersionExists = 0x80000000u, 222 | }; 223 | 224 | enum EClassCastFlags : uint64_t 225 | { 226 | CASTCLASS_None = 0x0000000000000000, 227 | CASTCLASS_UField = 0x0000000000000001, 228 | CASTCLASS_FInt8Property = 0x0000000000000002, 229 | CASTCLASS_UEnum = 0x0000000000000004, 230 | CASTCLASS_UStruct = 0x0000000000000008, 231 | CASTCLASS_UScriptStruct = 0x0000000000000010, 232 | CASTCLASS_UClass = 0x0000000000000020, 233 | CASTCLASS_FByteProperty = 0x0000000000000040, 234 | CASTCLASS_FIntProperty = 0x0000000000000080, 235 | CASTCLASS_FFloatProperty = 0x0000000000000100, 236 | CASTCLASS_FUInt64Property = 0x0000000000000200, 237 | CASTCLASS_FClassProperty = 0x0000000000000400, 238 | CASTCLASS_FUInt32Property = 0x0000000000000800, 239 | CASTCLASS_FInterfaceProperty = 0x0000000000001000, 240 | CASTCLASS_FNameProperty = 0x0000000000002000, 241 | CASTCLASS_FStrProperty = 0x0000000000004000, 242 | CASTCLASS_FProperty = 0x0000000000008000, 243 | CASTCLASS_FObjectProperty = 0x0000000000010000, 244 | CASTCLASS_FBoolProperty = 0x0000000000020000, 245 | CASTCLASS_FUInt16Property = 0x0000000000040000, 246 | CASTCLASS_UFunction = 0x0000000000080000, 247 | CASTCLASS_FStructProperty = 0x0000000000100000, 248 | CASTCLASS_FArrayProperty = 0x0000000000200000, 249 | CASTCLASS_FInt64Property = 0x0000000000400000, 250 | CASTCLASS_FDelegateProperty = 0x0000000000800000, 251 | CASTCLASS_FNumericProperty = 0x0000000001000000, 252 | CASTCLASS_FMulticastDelegateProperty = 0x0000000002000000, 253 | CASTCLASS_FObjectPropertyBase = 0x0000000004000000, 254 | CASTCLASS_FWeakObjectProperty = 0x0000000008000000, 255 | CASTCLASS_FLazyObjectProperty = 0x0000000010000000, 256 | CASTCLASS_FSoftObjectProperty = 0x0000000020000000, 257 | CASTCLASS_FTextProperty = 0x0000000040000000, 258 | CASTCLASS_FInt16Property = 0x0000000080000000, 259 | CASTCLASS_FDoubleProperty = 0x0000000100000000, 260 | CASTCLASS_FSoftClassProperty = 0x0000000200000000, 261 | CASTCLASS_UPackage = 0x0000000400000000, 262 | CASTCLASS_ULevel = 0x0000000800000000, 263 | CASTCLASS_AActor = 0x0000001000000000, 264 | CASTCLASS_APlayerController = 0x0000002000000000, 265 | CASTCLASS_APawn = 0x0000004000000000, 266 | CASTCLASS_USceneComponent = 0x0000008000000000, 267 | CASTCLASS_UPrimitiveComponent = 0x0000010000000000, 268 | CASTCLASS_USkinnedMeshComponent = 0x0000020000000000, 269 | CASTCLASS_USkeletalMeshComponent = 0x0000040000000000, 270 | CASTCLASS_UBlueprint = 0x0000080000000000, 271 | CASTCLASS_UDelegateFunction = 0x0000100000000000, 272 | CASTCLASS_UStaticMeshComponent = 0x0000200000000000, 273 | CASTCLASS_FMapProperty = 0x0000400000000000, 274 | CASTCLASS_FSetProperty = 0x0000800000000000, 275 | CASTCLASS_FEnumProperty = 0x0001000000000000, 276 | CASTCLASS_USparseDelegateFunction = 0x0002000000000000, 277 | CASTCLASS_FMulticastInlineDelegateProperty = 0x0004000000000000, 278 | CASTCLASS_FMulticastSparseDelegateProperty = 0x0008000000000000, 279 | CASTCLASS_FFieldPathProperty = 0x0010000000000000, 280 | }; 281 | 282 | enum EFunctionFlags : uint32_t 283 | { 284 | // Function flags. 285 | FUNC_None = 0x00000000, 286 | FUNC_Final = 0x00000001, 287 | // Function is final (prebindable, non-overridable function). 288 | FUNC_RequiredAPI = 0x00000002, 289 | // Indicates this function is DLL exported/imported. 290 | FUNC_BlueprintAuthorityOnly = 0x00000004, 291 | // Function will only run if the object has network authority 292 | FUNC_BlueprintCosmetic = 0x00000008, 293 | // Function is cosmetic in nature and should not be invoked on dedicated servers 294 | // FUNC_ = 0x00000010, // unused. 295 | // FUNC_ = 0x00000020, // unused. 296 | FUNC_Net = 0x00000040, 297 | // Function is network-replicated. 298 | FUNC_NetReliable = 0x00000080, 299 | // Function should be sent reliably on the network. 300 | FUNC_NetRequest = 0x00000100, 301 | // Function is sent to a net service 302 | FUNC_Exec = 0x00000200, 303 | // Executable from command line. 304 | FUNC_Native = 0x00000400, 305 | // Native function. 306 | FUNC_Event = 0x00000800, 307 | // Event function. 308 | FUNC_NetResponse = 0x00001000, 309 | // Function response from a net service 310 | FUNC_Static = 0x00002000, 311 | // Static function. 312 | FUNC_NetMulticast = 0x00004000, 313 | // Function is networked multicast Server -> All Clients 314 | FUNC_UbergraphFunction = 0x00008000, 315 | // Function is used as the merge 'ubergraph' for a blueprint, only assigned when using the persistent 'ubergraph' frame 316 | FUNC_MulticastDelegate = 0x00010000, 317 | // Function is a multi-cast delegate signature (also requires FUNC_Delegate to be set!) 318 | FUNC_Public = 0x00020000, 319 | // Function is accessible in all classes (if overridden, parameters must remain unchanged). 320 | FUNC_Private = 0x00040000, 321 | // Function is accessible only in the class it is defined in (cannot be overridden, but function name may be reused in subclasses. IOW: if overridden, parameters don't need to match, and Super.Func() cannot be accessed since it's private.) 322 | FUNC_Protected = 0x00080000, 323 | // Function is accessible only in the class it is defined in and subclasses (if overridden, parameters much remain unchanged). 324 | FUNC_Delegate = 0x00100000, 325 | // Function is delegate signature (either single-cast or multi-cast, depending on whether FUNC_MulticastDelegate is set.) 326 | FUNC_NetServer = 0x00200000, 327 | // Function is executed on servers (set by replication code if passes check) 328 | FUNC_HasOutParms = 0x00400000, 329 | // function has out (pass by reference) parameters 330 | FUNC_HasDefaults = 0x00800000, 331 | // function has structs that contain defaults 332 | FUNC_NetClient = 0x01000000, 333 | // function is executed on clients 334 | FUNC_DLLImport = 0x02000000, 335 | // function is imported from a DLL 336 | FUNC_BlueprintCallable = 0x04000000, 337 | // function can be called from blueprint code 338 | FUNC_BlueprintEvent = 0x08000000, 339 | // function can be overridden/implemented from a blueprint 340 | FUNC_BlueprintPure = 0x10000000, 341 | // function can be called from blueprint code, and is also pure (produces no side effects). If you set this, you should set FUNC_BlueprintCallable as well. 342 | FUNC_EditorOnly = 0x20000000, 343 | // function can only be called from an editor scrippt. 344 | FUNC_Const = 0x40000000, 345 | // function can be called from blueprint code, and only reads state (never writes state) 346 | FUNC_NetValidate = 0x80000000, 347 | // function must supply a _Validate implementation 348 | 349 | FUNC_AllFlags = 0xFFFFFFFF, 350 | }; 351 | 352 | enum class EArrayPropertyFlags 353 | { 354 | None, 355 | UsesMemoryImageAllocator 356 | }; 357 | 358 | enum EStructFlags 359 | { 360 | // State flags. 361 | STRUCT_NoFlags = 0x00000000, 362 | STRUCT_Native = 0x00000001, 363 | 364 | /** If set, this struct will be compared using native code */ 365 | STRUCT_IdenticalNative = 0x00000002, 366 | 367 | STRUCT_HasInstancedReference = 0x00000004, 368 | 369 | STRUCT_NoExport = 0x00000008, 370 | 371 | /** Indicates that this struct should always be serialized as a single unit */ 372 | STRUCT_Atomic = 0x00000010, 373 | 374 | /** Indicates that this struct uses binary serialization; it is unsafe to add/remove members from this struct without incrementing the package version */ 375 | STRUCT_Immutable = 0x00000020, 376 | 377 | /** If set, native code needs to be run to find referenced objects */ 378 | STRUCT_AddStructReferencedObjects = 0x00000040, 379 | 380 | /** Indicates that this struct should be exportable/importable at the DLL layer. Base structs must also be exportable for this to work. */ 381 | STRUCT_RequiredAPI = 0x00000200, 382 | 383 | /** If set, this struct will be serialized using the CPP net serializer */ 384 | STRUCT_NetSerializeNative = 0x00000400, 385 | 386 | /** If set, this struct will be serialized using the CPP serializer */ 387 | STRUCT_SerializeNative = 0x00000800, 388 | 389 | /** If set, this struct will be copied using the CPP operator= */ 390 | STRUCT_CopyNative = 0x00001000, 391 | 392 | /** If set, this struct will be copied using memcpy */ 393 | STRUCT_IsPlainOldData = 0x00002000, 394 | 395 | /** If set, this struct has no destructor and non will be called. STRUCT_IsPlainOldData implies STRUCT_NoDestructor */ 396 | STRUCT_NoDestructor = 0x00004000, 397 | 398 | /** If set, this struct will not be constructed because it is assumed that memory is zero before construction. */ 399 | STRUCT_ZeroConstructor = 0x00008000, 400 | 401 | /** If set, native code will be used to export text */ 402 | STRUCT_ExportTextItemNative = 0x00010000, 403 | 404 | /** If set, native code will be used to export text */ 405 | STRUCT_ImportTextItemNative = 0x00020000, 406 | 407 | /** If set, this struct will have PostSerialize called on it after CPP serializer or tagged property serialization is complete */ 408 | STRUCT_PostSerializeNative = 0x00040000, 409 | 410 | /** If set, this struct will have SerializeFromMismatchedTag called on it if a mismatched tag is encountered. */ 411 | STRUCT_SerializeFromMismatchedTag = 0x00080000, 412 | 413 | /** If set, this struct will be serialized using the CPP net delta serializer */ 414 | STRUCT_NetDeltaSerializeNative = 0x00100000, 415 | 416 | /** If set, this struct will be have PostScriptConstruct called on it after a temporary object is constructed in a running blueprint */ 417 | STRUCT_PostScriptConstruct = 0x00200000, 418 | 419 | /** If set, this struct can share net serialization state across connections */ 420 | STRUCT_NetSharedSerialization = 0x00400000, 421 | 422 | /** If set, this struct has been cleaned and sanitized (trashed) and should not be used */ 423 | STRUCT_Trashed = 0x00800000, 424 | 425 | /** If set, this structure has been replaced via reinstancing */ 426 | STRUCT_NewerVersionExists = 0x01000000, 427 | 428 | /** Struct flags that are automatically inherited */ 429 | STRUCT_Inherit = STRUCT_HasInstancedReference | STRUCT_Atomic, 430 | 431 | /** Flags that are always computed, never loaded or done with code generation */ 432 | STRUCT_ComputedFlags = STRUCT_NetDeltaSerializeNative | STRUCT_NetSerializeNative | STRUCT_SerializeNative | STRUCT_PostSerializeNative | STRUCT_CopyNative | STRUCT_IsPlainOldData | STRUCT_NoDestructor | STRUCT_ZeroConstructor | STRUCT_IdenticalNative | STRUCT_AddStructReferencedObjects | STRUCT_ExportTextItemNative | STRUCT_ImportTextItemNative | STRUCT_SerializeFromMismatchedTag | STRUCT_PostScriptConstruct | STRUCT_NetSharedSerialization 433 | }; -------------------------------------------------------------------------------- /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/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" -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/parallel_hashmap/phmap_bits.h: -------------------------------------------------------------------------------- 1 | #if !defined(phmap_bits_h_guard_) 2 | #define phmap_bits_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 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | // Includes work from abseil-cpp (https://github.com/abseil/abseil-cpp) 20 | // with modifications. 21 | // 22 | // Copyright 2018 The Abseil Authors. 23 | // 24 | // Licensed under the Apache License, Version 2.0 (the "License"); 25 | // you may not use this file except in compliance with the License. 26 | // You may obtain a copy of the License at 27 | // 28 | // https://www.apache.org/licenses/LICENSE-2.0 29 | // 30 | // Unless required by applicable law or agreed to in writing, software 31 | // distributed under the License is distributed on an "AS IS" BASIS, 32 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 33 | // See the License for the specific language governing permissions and 34 | // limitations under the License. 35 | // --------------------------------------------------------------------------- 36 | 37 | // The following guarantees declaration of the byte swap functions 38 | #ifdef _MSC_VER 39 | #include // NOLINT(build/include) 40 | #elif defined(__APPLE__) 41 | // Mac OS X / Darwin features 42 | #include 43 | #elif defined(__FreeBSD__) 44 | #include 45 | #elif defined(__GLIBC__) 46 | #include // IWYU pragma: export 47 | #endif 48 | 49 | #include 50 | #include 51 | #include "phmap_config.h" 52 | 53 | #ifdef _MSC_VER 54 | #pragma warning(push) 55 | #pragma warning(disable : 4514) // unreferenced inline function has been removed 56 | #endif 57 | 58 | // ----------------------------------------------------------------------------- 59 | // unaligned APIs 60 | // ----------------------------------------------------------------------------- 61 | // Portable handling of unaligned loads, stores, and copies. 62 | // On some platforms, like ARM, the copy functions can be more efficient 63 | // then a load and a store. 64 | // ----------------------------------------------------------------------------- 65 | 66 | #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\ 67 | defined(MEMORY_SANITIZER) 68 | #include 69 | 70 | extern "C" { 71 | uint16_t __sanitizer_unaligned_load16(const void *p); 72 | uint32_t __sanitizer_unaligned_load32(const void *p); 73 | uint64_t __sanitizer_unaligned_load64(const void *p); 74 | void __sanitizer_unaligned_store16(void *p, uint16_t v); 75 | void __sanitizer_unaligned_store32(void *p, uint32_t v); 76 | void __sanitizer_unaligned_store64(void *p, uint64_t v); 77 | } // extern "C" 78 | 79 | namespace phmap { 80 | namespace bits { 81 | 82 | inline uint16_t UnalignedLoad16(const void *p) { 83 | return __sanitizer_unaligned_load16(p); 84 | } 85 | 86 | inline uint32_t UnalignedLoad32(const void *p) { 87 | return __sanitizer_unaligned_load32(p); 88 | } 89 | 90 | inline uint64_t UnalignedLoad64(const void *p) { 91 | return __sanitizer_unaligned_load64(p); 92 | } 93 | 94 | inline void UnalignedStore16(void *p, uint16_t v) { 95 | __sanitizer_unaligned_store16(p, v); 96 | } 97 | 98 | inline void UnalignedStore32(void *p, uint32_t v) { 99 | __sanitizer_unaligned_store32(p, v); 100 | } 101 | 102 | inline void UnalignedStore64(void *p, uint64_t v) { 103 | __sanitizer_unaligned_store64(p, v); 104 | } 105 | 106 | } // namespace bits 107 | } // namespace phmap 108 | 109 | #define PHMAP_INTERNAL_UNALIGNED_LOAD16(_p) (phmap::bits::UnalignedLoad16(_p)) 110 | #define PHMAP_INTERNAL_UNALIGNED_LOAD32(_p) (phmap::bits::UnalignedLoad32(_p)) 111 | #define PHMAP_INTERNAL_UNALIGNED_LOAD64(_p) (phmap::bits::UnalignedLoad64(_p)) 112 | 113 | #define PHMAP_INTERNAL_UNALIGNED_STORE16(_p, _val) (phmap::bits::UnalignedStore16(_p, _val)) 114 | #define PHMAP_INTERNAL_UNALIGNED_STORE32(_p, _val) (phmap::bits::UnalignedStore32(_p, _val)) 115 | #define PHMAP_INTERNAL_UNALIGNED_STORE64(_p, _val) (phmap::bits::UnalignedStore64(_p, _val)) 116 | 117 | #else 118 | 119 | namespace phmap { 120 | namespace bits { 121 | 122 | inline uint16_t UnalignedLoad16(const void *p) { 123 | uint16_t t; 124 | memcpy(&t, p, sizeof t); 125 | return t; 126 | } 127 | 128 | inline uint32_t UnalignedLoad32(const void *p) { 129 | uint32_t t; 130 | memcpy(&t, p, sizeof t); 131 | return t; 132 | } 133 | 134 | inline uint64_t UnalignedLoad64(const void *p) { 135 | uint64_t t; 136 | memcpy(&t, p, sizeof t); 137 | return t; 138 | } 139 | 140 | inline void UnalignedStore16(void *p, uint16_t v) { memcpy(p, &v, sizeof v); } 141 | 142 | inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); } 143 | 144 | inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); } 145 | 146 | } // namespace bits 147 | } // namespace phmap 148 | 149 | #define PHMAP_INTERNAL_UNALIGNED_LOAD16(_p) (phmap::bits::UnalignedLoad16(_p)) 150 | #define PHMAP_INTERNAL_UNALIGNED_LOAD32(_p) (phmap::bits::UnalignedLoad32(_p)) 151 | #define PHMAP_INTERNAL_UNALIGNED_LOAD64(_p) (phmap::bits::UnalignedLoad64(_p)) 152 | 153 | #define PHMAP_INTERNAL_UNALIGNED_STORE16(_p, _val) (phmap::bits::UnalignedStore16(_p, _val)) 154 | #define PHMAP_INTERNAL_UNALIGNED_STORE32(_p, _val) (phmap::bits::UnalignedStore32(_p, _val)) 155 | #define PHMAP_INTERNAL_UNALIGNED_STORE64(_p, _val) (phmap::bits::UnalignedStore64(_p, _val)) 156 | 157 | #endif 158 | 159 | // ----------------------------------------------------------------------------- 160 | // File: optimization.h 161 | // ----------------------------------------------------------------------------- 162 | 163 | #if defined(__pnacl__) 164 | #define PHMAP_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } 165 | #elif defined(__clang__) 166 | // Clang will not tail call given inline volatile assembly. 167 | #define PHMAP_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") 168 | #elif defined(__GNUC__) 169 | // GCC will not tail call given inline volatile assembly. 170 | #define PHMAP_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") 171 | #elif defined(_MSC_VER) 172 | #include 173 | // The __nop() intrinsic blocks the optimisation. 174 | #define PHMAP_BLOCK_TAIL_CALL_OPTIMIZATION() __nop() 175 | #else 176 | #define PHMAP_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } 177 | #endif 178 | 179 | #if defined(__GNUC__) 180 | #pragma GCC diagnostic push 181 | #pragma GCC diagnostic ignored "-Wpedantic" 182 | #endif 183 | 184 | #ifdef PHMAP_HAVE_INTRINSIC_INT128 185 | __extension__ typedef unsigned __int128 phmap_uint128; 186 | inline uint64_t umul128(uint64_t a, uint64_t b, uint64_t* high) 187 | { 188 | auto result = static_cast(a) * static_cast(b); 189 | *high = static_cast(result >> 64); 190 | return static_cast(result); 191 | } 192 | #define PHMAP_HAS_UMUL128 1 193 | #elif (defined(_MSC_VER)) 194 | #if defined(_M_X64) 195 | #pragma intrinsic(_umul128) 196 | inline uint64_t umul128(uint64_t a, uint64_t b, uint64_t* high) 197 | { 198 | return _umul128(a, b, high); 199 | } 200 | #define PHMAP_HAS_UMUL128 1 201 | #endif 202 | #endif 203 | 204 | #if defined(__GNUC__) 205 | #pragma GCC diagnostic pop 206 | #endif 207 | 208 | #if defined(__GNUC__) 209 | // Cache line alignment 210 | #if defined(__i386__) || defined(__x86_64__) 211 | #define PHMAP_CACHELINE_SIZE 64 212 | #elif defined(__powerpc64__) 213 | #define PHMAP_CACHELINE_SIZE 128 214 | #elif defined(__aarch64__) 215 | // We would need to read special register ctr_el0 to find out L1 dcache size. 216 | // This value is a good estimate based on a real aarch64 machine. 217 | #define PHMAP_CACHELINE_SIZE 64 218 | #elif defined(__arm__) 219 | // Cache line sizes for ARM: These values are not strictly correct since 220 | // cache line sizes depend on implementations, not architectures. There 221 | // are even implementations with cache line sizes configurable at boot 222 | // time. 223 | #if defined(__ARM_ARCH_5T__) 224 | #define PHMAP_CACHELINE_SIZE 32 225 | #elif defined(__ARM_ARCH_7A__) 226 | #define PHMAP_CACHELINE_SIZE 64 227 | #endif 228 | #endif 229 | 230 | #ifndef PHMAP_CACHELINE_SIZE 231 | // A reasonable default guess. Note that overestimates tend to waste more 232 | // space, while underestimates tend to waste more time. 233 | #define PHMAP_CACHELINE_SIZE 64 234 | #endif 235 | 236 | #define PHMAP_CACHELINE_ALIGNED __attribute__((aligned(PHMAP_CACHELINE_SIZE))) 237 | #elif defined(_MSC_VER) 238 | #define PHMAP_CACHELINE_SIZE 64 239 | #define PHMAP_CACHELINE_ALIGNED __declspec(align(PHMAP_CACHELINE_SIZE)) 240 | #else 241 | #define PHMAP_CACHELINE_SIZE 64 242 | #define PHMAP_CACHELINE_ALIGNED 243 | #endif 244 | 245 | 246 | #if PHMAP_HAVE_BUILTIN(__builtin_expect) || \ 247 | (defined(__GNUC__) && !defined(__clang__)) 248 | #define PHMAP_PREDICT_FALSE(x) (__builtin_expect(x, 0)) 249 | #define PHMAP_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) 250 | #else 251 | #define PHMAP_PREDICT_FALSE(x) (x) 252 | #define PHMAP_PREDICT_TRUE(x) (x) 253 | #endif 254 | 255 | // ----------------------------------------------------------------------------- 256 | // File: bits.h 257 | // ----------------------------------------------------------------------------- 258 | 259 | #if defined(_MSC_VER) 260 | // We can achieve something similar to attribute((always_inline)) with MSVC by 261 | // using the __forceinline keyword, however this is not perfect. MSVC is 262 | // much less aggressive about inlining, and even with the __forceinline keyword. 263 | #define PHMAP_BASE_INTERNAL_FORCEINLINE __forceinline 264 | #else 265 | // Use default attribute inline. 266 | #define PHMAP_BASE_INTERNAL_FORCEINLINE inline PHMAP_ATTRIBUTE_ALWAYS_INLINE 267 | #endif 268 | 269 | 270 | namespace phmap { 271 | namespace base_internal { 272 | 273 | PHMAP_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64Slow(uint64_t n) { 274 | int zeroes = 60; 275 | if (n >> 32) zeroes -= 32, n >>= 32; 276 | if (n >> 16) zeroes -= 16, n >>= 16; 277 | if (n >> 8) zeroes -= 8, n >>= 8; 278 | if (n >> 4) zeroes -= 4, n >>= 4; 279 | return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes; 280 | } 281 | 282 | PHMAP_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64(uint64_t n) { 283 | #if defined(_MSC_VER) && defined(_M_X64) 284 | // MSVC does not have __buitin_clzll. Use _BitScanReverse64. 285 | unsigned long result = 0; // NOLINT(runtime/int) 286 | if (_BitScanReverse64(&result, n)) { 287 | return (int)(63 - result); 288 | } 289 | return 64; 290 | #elif defined(_MSC_VER) && !defined(__clang__) 291 | // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse 292 | unsigned long result = 0; // NOLINT(runtime/int) 293 | if ((n >> 32) && _BitScanReverse(&result, (unsigned long)(n >> 32))) { 294 | return 31 - result; 295 | } 296 | if (_BitScanReverse(&result, (unsigned long)n)) { 297 | return 63 - result; 298 | } 299 | return 64; 300 | #elif defined(__GNUC__) || defined(__clang__) 301 | // Use __builtin_clzll, which uses the following instructions: 302 | // x86: bsr 303 | // ARM64: clz 304 | // PPC: cntlzd 305 | static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int) 306 | "__builtin_clzll does not take 64-bit arg"); 307 | 308 | // Handle 0 as a special case because __builtin_clzll(0) is undefined. 309 | if (n == 0) { 310 | return 64; 311 | } 312 | return __builtin_clzll(n); 313 | #else 314 | return CountLeadingZeros64Slow(n); 315 | #endif 316 | } 317 | 318 | PHMAP_BASE_INTERNAL_FORCEINLINE uint32_t CountLeadingZeros32Slow(uint64_t n) { 319 | uint32_t zeroes = 28; 320 | if (n >> 16) zeroes -= 16, n >>= 16; 321 | if (n >> 8) zeroes -= 8, n >>= 8; 322 | if (n >> 4) zeroes -= 4, n >>= 4; 323 | return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes; 324 | } 325 | 326 | PHMAP_BASE_INTERNAL_FORCEINLINE uint32_t CountLeadingZeros32(uint32_t n) { 327 | #if defined(_MSC_VER) && !defined(__clang__) 328 | unsigned long result = 0; // NOLINT(runtime/int) 329 | if (_BitScanReverse(&result, n)) { 330 | return (uint32_t)(31 - result); 331 | } 332 | return 32; 333 | #elif defined(__GNUC__) || defined(__clang__) 334 | // Use __builtin_clz, which uses the following instructions: 335 | // x86: bsr 336 | // ARM64: clz 337 | // PPC: cntlzd 338 | static_assert(sizeof(int) == sizeof(n), 339 | "__builtin_clz does not take 32-bit arg"); 340 | 341 | // Handle 0 as a special case because __builtin_clz(0) is undefined. 342 | if (n == 0) { 343 | return 32; 344 | } 345 | return __builtin_clz(n); 346 | #else 347 | return CountLeadingZeros32Slow(n); 348 | #endif 349 | } 350 | 351 | PHMAP_BASE_INTERNAL_FORCEINLINE uint32_t CountTrailingZerosNonZero64Slow(uint64_t n) { 352 | uint32_t c = 63; 353 | n &= ~n + 1; 354 | if (n & 0x00000000FFFFFFFF) c -= 32; 355 | if (n & 0x0000FFFF0000FFFF) c -= 16; 356 | if (n & 0x00FF00FF00FF00FF) c -= 8; 357 | if (n & 0x0F0F0F0F0F0F0F0F) c -= 4; 358 | if (n & 0x3333333333333333) c -= 2; 359 | if (n & 0x5555555555555555) c -= 1; 360 | return c; 361 | } 362 | 363 | PHMAP_BASE_INTERNAL_FORCEINLINE uint32_t CountTrailingZerosNonZero64(uint64_t n) { 364 | #if defined(_MSC_VER) && !defined(__clang__) && defined(_M_X64) 365 | unsigned long result = 0; // NOLINT(runtime/int) 366 | _BitScanForward64(&result, n); 367 | return (uint32_t)result; 368 | #elif defined(_MSC_VER) && !defined(__clang__) 369 | unsigned long result = 0; // NOLINT(runtime/int) 370 | if (static_cast(n) == 0) { 371 | _BitScanForward(&result, (unsigned long)(n >> 32)); 372 | return result + 32; 373 | } 374 | _BitScanForward(&result, (unsigned long)n); 375 | return result; 376 | #elif defined(__GNUC__) || defined(__clang__) 377 | static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int) 378 | "__builtin_ctzll does not take 64-bit arg"); 379 | return __builtin_ctzll(n); 380 | #else 381 | return CountTrailingZerosNonZero64Slow(n); 382 | #endif 383 | } 384 | 385 | PHMAP_BASE_INTERNAL_FORCEINLINE uint32_t CountTrailingZerosNonZero32Slow(uint32_t n) { 386 | uint32_t c = 31; 387 | n &= ~n + 1; 388 | if (n & 0x0000FFFF) c -= 16; 389 | if (n & 0x00FF00FF) c -= 8; 390 | if (n & 0x0F0F0F0F) c -= 4; 391 | if (n & 0x33333333) c -= 2; 392 | if (n & 0x55555555) c -= 1; 393 | return c; 394 | } 395 | 396 | PHMAP_BASE_INTERNAL_FORCEINLINE uint32_t CountTrailingZerosNonZero32(uint32_t n) { 397 | #if defined(_MSC_VER) && !defined(__clang__) 398 | unsigned long result = 0; // NOLINT(runtime/int) 399 | _BitScanForward(&result, n); 400 | return (uint32_t)result; 401 | #elif defined(__GNUC__) || defined(__clang__) 402 | static_assert(sizeof(int) == sizeof(n), 403 | "__builtin_ctz does not take 32-bit arg"); 404 | return __builtin_ctz(n); 405 | #else 406 | return CountTrailingZerosNonZero32Slow(n); 407 | #endif 408 | } 409 | 410 | #undef PHMAP_BASE_INTERNAL_FORCEINLINE 411 | 412 | } // namespace base_internal 413 | } // namespace phmap 414 | 415 | // ----------------------------------------------------------------------------- 416 | // File: endian.h 417 | // ----------------------------------------------------------------------------- 418 | 419 | namespace phmap { 420 | 421 | // Use compiler byte-swapping intrinsics if they are available. 32-bit 422 | // and 64-bit versions are available in Clang and GCC as of GCC 4.3.0. 423 | // The 16-bit version is available in Clang and GCC only as of GCC 4.8.0. 424 | // For simplicity, we enable them all only for GCC 4.8.0 or later. 425 | #if defined(__clang__) || \ 426 | (defined(__GNUC__) && \ 427 | ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ >= 5)) 428 | 429 | inline uint64_t gbswap_64(uint64_t host_int) { 430 | return __builtin_bswap64(host_int); 431 | } 432 | inline uint32_t gbswap_32(uint32_t host_int) { 433 | return __builtin_bswap32(host_int); 434 | } 435 | inline uint16_t gbswap_16(uint16_t host_int) { 436 | return __builtin_bswap16(host_int); 437 | } 438 | 439 | #elif defined(_MSC_VER) 440 | 441 | inline uint64_t gbswap_64(uint64_t host_int) { 442 | return _byteswap_uint64(host_int); 443 | } 444 | inline uint32_t gbswap_32(uint32_t host_int) { 445 | return _byteswap_ulong(host_int); 446 | } 447 | inline uint16_t gbswap_16(uint16_t host_int) { 448 | return _byteswap_ushort(host_int); 449 | } 450 | 451 | #elif defined(__APPLE__) 452 | 453 | inline uint64_t gbswap_64(uint64_t host_int) { return OSSwapInt16(host_int); } 454 | inline uint32_t gbswap_32(uint32_t host_int) { return OSSwapInt32(host_int); } 455 | inline uint16_t gbswap_16(uint16_t host_int) { return OSSwapInt64(host_int); } 456 | 457 | #else 458 | 459 | inline uint64_t gbswap_64(uint64_t host_int) { 460 | #if defined(__GNUC__) && defined(__x86_64__) && !defined(__APPLE__) 461 | // Adapted from /usr/include/byteswap.h. Not available on Mac. 462 | if (__builtin_constant_p(host_int)) { 463 | return __bswap_constant_64(host_int); 464 | } else { 465 | uint64_t result; 466 | __asm__("bswap %0" : "=r"(result) : "0"(host_int)); 467 | return result; 468 | } 469 | #elif defined(__GLIBC__) 470 | return bswap_64(host_int); 471 | #else 472 | return (((host_int & uint64_t{0xFF}) << 56) | 473 | ((host_int & uint64_t{0xFF00}) << 40) | 474 | ((host_int & uint64_t{0xFF0000}) << 24) | 475 | ((host_int & uint64_t{0xFF000000}) << 8) | 476 | ((host_int & uint64_t{0xFF00000000}) >> 8) | 477 | ((host_int & uint64_t{0xFF0000000000}) >> 24) | 478 | ((host_int & uint64_t{0xFF000000000000}) >> 40) | 479 | ((host_int & uint64_t{0xFF00000000000000}) >> 56)); 480 | #endif // bswap_64 481 | } 482 | 483 | inline uint32_t gbswap_32(uint32_t host_int) { 484 | #if defined(__GLIBC__) 485 | return bswap_32(host_int); 486 | #else 487 | return (((host_int & uint32_t{0xFF}) << 24) | 488 | ((host_int & uint32_t{0xFF00}) << 8) | 489 | ((host_int & uint32_t{0xFF0000}) >> 8) | 490 | ((host_int & uint32_t{0xFF000000}) >> 24)); 491 | #endif 492 | } 493 | 494 | inline uint16_t gbswap_16(uint16_t host_int) { 495 | #if defined(__GLIBC__) 496 | return bswap_16(host_int); 497 | #else 498 | return (((host_int & uint16_t{0xFF}) << 8) | 499 | ((host_int & uint16_t{0xFF00}) >> 8)); 500 | #endif 501 | } 502 | 503 | #endif // intrinics available 504 | 505 | #ifdef PHMAP_IS_LITTLE_ENDIAN 506 | 507 | // Definitions for ntohl etc. that don't require us to include 508 | // netinet/in.h. We wrap gbswap_32 and gbswap_16 in functions rather 509 | // than just #defining them because in debug mode, gcc doesn't 510 | // correctly handle the (rather involved) definitions of bswap_32. 511 | // gcc guarantees that inline functions are as fast as macros, so 512 | // this isn't a performance hit. 513 | inline uint16_t ghtons(uint16_t x) { return gbswap_16(x); } 514 | inline uint32_t ghtonl(uint32_t x) { return gbswap_32(x); } 515 | inline uint64_t ghtonll(uint64_t x) { return gbswap_64(x); } 516 | 517 | #elif defined PHMAP_IS_BIG_ENDIAN 518 | 519 | // These definitions are simpler on big-endian machines 520 | // These are functions instead of macros to avoid self-assignment warnings 521 | // on calls such as "i = ghtnol(i);". This also provides type checking. 522 | inline uint16_t ghtons(uint16_t x) { return x; } 523 | inline uint32_t ghtonl(uint32_t x) { return x; } 524 | inline uint64_t ghtonll(uint64_t x) { return x; } 525 | 526 | #else 527 | #error \ 528 | "Unsupported byte order: Either PHMAP_IS_BIG_ENDIAN or " \ 529 | "PHMAP_IS_LITTLE_ENDIAN must be defined" 530 | #endif // byte order 531 | 532 | inline uint16_t gntohs(uint16_t x) { return ghtons(x); } 533 | inline uint32_t gntohl(uint32_t x) { return ghtonl(x); } 534 | inline uint64_t gntohll(uint64_t x) { return ghtonll(x); } 535 | 536 | // Utilities to convert numbers between the current hosts's native byte 537 | // order and little-endian byte order 538 | // 539 | // Load/Store methods are alignment safe 540 | namespace little_endian { 541 | // Conversion functions. 542 | #ifdef PHMAP_IS_LITTLE_ENDIAN 543 | 544 | inline uint16_t FromHost16(uint16_t x) { return x; } 545 | inline uint16_t ToHost16(uint16_t x) { return x; } 546 | 547 | inline uint32_t FromHost32(uint32_t x) { return x; } 548 | inline uint32_t ToHost32(uint32_t x) { return x; } 549 | 550 | inline uint64_t FromHost64(uint64_t x) { return x; } 551 | inline uint64_t ToHost64(uint64_t x) { return x; } 552 | 553 | inline constexpr bool IsLittleEndian() { return true; } 554 | 555 | #elif defined PHMAP_IS_BIG_ENDIAN 556 | 557 | inline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); } 558 | inline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); } 559 | 560 | inline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); } 561 | inline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); } 562 | 563 | inline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); } 564 | inline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); } 565 | 566 | inline constexpr bool IsLittleEndian() { return false; } 567 | 568 | #endif /* ENDIAN */ 569 | 570 | // Functions to do unaligned loads and stores in little-endian order. 571 | // ------------------------------------------------------------------ 572 | inline uint16_t Load16(const void *p) { 573 | return ToHost16(PHMAP_INTERNAL_UNALIGNED_LOAD16(p)); 574 | } 575 | 576 | inline void Store16(void *p, uint16_t v) { 577 | PHMAP_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v)); 578 | } 579 | 580 | inline uint32_t Load32(const void *p) { 581 | return ToHost32(PHMAP_INTERNAL_UNALIGNED_LOAD32(p)); 582 | } 583 | 584 | inline void Store32(void *p, uint32_t v) { 585 | PHMAP_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v)); 586 | } 587 | 588 | inline uint64_t Load64(const void *p) { 589 | return ToHost64(PHMAP_INTERNAL_UNALIGNED_LOAD64(p)); 590 | } 591 | 592 | inline void Store64(void *p, uint64_t v) { 593 | PHMAP_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v)); 594 | } 595 | 596 | } // namespace little_endian 597 | 598 | // Utilities to convert numbers between the current hosts's native byte 599 | // order and big-endian byte order (same as network byte order) 600 | // 601 | // Load/Store methods are alignment safe 602 | namespace big_endian { 603 | #ifdef PHMAP_IS_LITTLE_ENDIAN 604 | 605 | inline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); } 606 | inline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); } 607 | 608 | inline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); } 609 | inline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); } 610 | 611 | inline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); } 612 | inline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); } 613 | 614 | inline constexpr bool IsLittleEndian() { return true; } 615 | 616 | #elif defined PHMAP_IS_BIG_ENDIAN 617 | 618 | inline uint16_t FromHost16(uint16_t x) { return x; } 619 | inline uint16_t ToHost16(uint16_t x) { return x; } 620 | 621 | inline uint32_t FromHost32(uint32_t x) { return x; } 622 | inline uint32_t ToHost32(uint32_t x) { return x; } 623 | 624 | inline uint64_t FromHost64(uint64_t x) { return x; } 625 | inline uint64_t ToHost64(uint64_t x) { return x; } 626 | 627 | inline constexpr bool IsLittleEndian() { return false; } 628 | 629 | #endif /* ENDIAN */ 630 | 631 | // Functions to do unaligned loads and stores in big-endian order. 632 | inline uint16_t Load16(const void *p) { 633 | return ToHost16(PHMAP_INTERNAL_UNALIGNED_LOAD16(p)); 634 | } 635 | 636 | inline void Store16(void *p, uint16_t v) { 637 | PHMAP_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v)); 638 | } 639 | 640 | inline uint32_t Load32(const void *p) { 641 | return ToHost32(PHMAP_INTERNAL_UNALIGNED_LOAD32(p)); 642 | } 643 | 644 | inline void Store32(void *p, uint32_t v) { 645 | PHMAP_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v)); 646 | } 647 | 648 | inline uint64_t Load64(const void *p) { 649 | return ToHost64(PHMAP_INTERNAL_UNALIGNED_LOAD64(p)); 650 | } 651 | 652 | inline void Store64(void *p, uint64_t v) { 653 | PHMAP_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v)); 654 | } 655 | 656 | } // namespace big_endian 657 | 658 | } // namespace phmap 659 | 660 | #ifdef _MSC_VER 661 | #pragma warning(pop) 662 | #endif 663 | 664 | #endif // phmap_bits_h_guard_ 665 | -------------------------------------------------------------------------------- /FortKitInsider/parallel_hashmap/phmap_config.h: -------------------------------------------------------------------------------- 1 | #if !defined(phmap_config_h_guard_) 2 | #define phmap_config_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 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | // Includes work from abseil-cpp (https://github.com/abseil/abseil-cpp) 20 | // with modifications. 21 | // 22 | // Copyright 2018 The Abseil Authors. 23 | // 24 | // Licensed under the Apache License, Version 2.0 (the "License"); 25 | // you may not use this file except in compliance with the License. 26 | // You may obtain a copy of the License at 27 | // 28 | // https://www.apache.org/licenses/LICENSE-2.0 29 | // 30 | // Unless required by applicable law or agreed to in writing, software 31 | // distributed under the License is distributed on an "AS IS" BASIS, 32 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 33 | // See the License for the specific language governing permissions and 34 | // limitations under the License. 35 | // --------------------------------------------------------------------------- 36 | 37 | #define PHMAP_VERSION_MAJOR 1 38 | #define PHMAP_VERSION_MINOR 3 39 | #define PHMAP_VERSION_PATCH 8 40 | 41 | // Included for the __GLIBC__ macro (or similar macros on other systems). 42 | #include 43 | 44 | #ifdef __cplusplus 45 | // Included for __GLIBCXX__, _LIBCPP_VERSION 46 | #include 47 | #endif // __cplusplus 48 | 49 | #if defined(__APPLE__) 50 | // Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED, 51 | // __IPHONE_8_0. 52 | #include 53 | #include 54 | #endif 55 | 56 | #define PHMAP_XSTR(x) PHMAP_STR(x) 57 | #define PHMAP_STR(x) #x 58 | #define PHMAP_VAR_NAME_VALUE(var) #var "=" PHMAP_STR(var) 59 | 60 | // ----------------------------------------------------------------------------- 61 | // Some sanity checks 62 | // ----------------------------------------------------------------------------- 63 | //#if defined(__CYGWIN__) 64 | // #error "Cygwin is not supported." 65 | //#endif 66 | 67 | #if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023918 && !defined(__clang__) 68 | #error "phmap requires Visual Studio 2015 Update 2 or higher." 69 | #endif 70 | 71 | // We support gcc 4.7 and later. 72 | #if defined(__GNUC__) && !defined(__clang__) 73 | #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) 74 | #error "phmap requires gcc 4.7 or higher." 75 | #endif 76 | #endif 77 | 78 | // We support Apple Xcode clang 4.2.1 (version 421.11.65) and later. 79 | // This corresponds to Apple Xcode version 4.5. 80 | #if defined(__apple_build_version__) && __apple_build_version__ < 4211165 81 | #error "phmap requires __apple_build_version__ of 4211165 or higher." 82 | #endif 83 | 84 | // Enforce C++11 as the minimum. 85 | #if defined(__cplusplus) && !defined(_MSC_VER) 86 | #if __cplusplus < 201103L 87 | #error "C++ versions less than C++11 are not supported." 88 | #endif 89 | #endif 90 | 91 | // We have chosen glibc 2.12 as the minimum 92 | #if defined(__GLIBC__) && defined(__GLIBC_PREREQ) 93 | #if !__GLIBC_PREREQ(2, 12) 94 | #error "Minimum required version of glibc is 2.12." 95 | #endif 96 | #endif 97 | 98 | #if defined(_STLPORT_VERSION) 99 | #error "STLPort is not supported." 100 | #endif 101 | 102 | #if CHAR_BIT != 8 103 | #error "phmap assumes CHAR_BIT == 8." 104 | #endif 105 | 106 | // phmap currently assumes that an int is 4 bytes. 107 | #if INT_MAX < 2147483647 108 | #error "phmap assumes that int is at least 4 bytes. " 109 | #endif 110 | 111 | 112 | 113 | // ----------------------------------------------------------------------------- 114 | // Compiler Feature Checks 115 | // ----------------------------------------------------------------------------- 116 | 117 | #ifdef __has_builtin 118 | #define PHMAP_HAVE_BUILTIN(x) __has_builtin(x) 119 | #else 120 | #define PHMAP_HAVE_BUILTIN(x) 0 121 | #endif 122 | 123 | #if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703) || __cplusplus >= 201703 124 | #define PHMAP_HAVE_CC17 1 125 | #else 126 | #define PHMAP_HAVE_CC17 0 127 | #endif 128 | 129 | #define PHMAP_BRANCHLESS 1 130 | 131 | #ifdef __has_feature 132 | #define PHMAP_HAVE_FEATURE(f) __has_feature(f) 133 | #else 134 | #define PHMAP_HAVE_FEATURE(f) 0 135 | #endif 136 | 137 | // Portable check for GCC minimum version: 138 | // https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html 139 | #if defined(__GNUC__) && defined(__GNUC_MINOR__) 140 | #define PHMAP_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) 141 | #else 142 | #define PHMAP_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) 0 143 | #endif 144 | 145 | #if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) 146 | #define PHMAP_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y)) 147 | #else 148 | #define PHMAP_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) 0 149 | #endif 150 | 151 | // ------------------------------------------------------------------- 152 | // Checks whether C++11's `thread_local` storage duration specifier is 153 | // supported. 154 | // ------------------------------------------------------------------- 155 | #ifdef PHMAP_HAVE_THREAD_LOCAL 156 | #error PHMAP_HAVE_THREAD_LOCAL cannot be directly set 157 | #elif defined(__APPLE__) 158 | #if __has_feature(cxx_thread_local) && \ 159 | !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0) 160 | #define PHMAP_HAVE_THREAD_LOCAL 1 161 | #endif 162 | #else // !defined(__APPLE__) 163 | #define PHMAP_HAVE_THREAD_LOCAL 1 164 | #endif 165 | 166 | #if defined(__ANDROID__) && defined(__clang__) 167 | 168 | #if __has_include() 169 | #include 170 | #endif // __has_include() 171 | 172 | #if defined(__ANDROID__) && defined(__clang__) && defined(__NDK_MAJOR__) && \ 173 | defined(__NDK_MINOR__) && \ 174 | ((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1))) 175 | #undef PHMAP_HAVE_TLS 176 | #undef PHMAP_HAVE_THREAD_LOCAL 177 | #endif 178 | #endif 179 | 180 | // ------------------------------------------------------------ 181 | // Checks whether the __int128 compiler extension for a 128-bit 182 | // integral type is supported. 183 | // ------------------------------------------------------------ 184 | #ifdef PHMAP_HAVE_INTRINSIC_INT128 185 | #error PHMAP_HAVE_INTRINSIC_INT128 cannot be directly set 186 | #elif defined(__SIZEOF_INT128__) 187 | #if (defined(__clang__) && !defined(_WIN32) && !defined(__aarch64__)) || \ 188 | (defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \ 189 | (defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__)) 190 | #define PHMAP_HAVE_INTRINSIC_INT128 1 191 | #elif defined(__CUDACC__) 192 | #if __CUDACC_VER__ >= 70000 193 | #define PHMAP_HAVE_INTRINSIC_INT128 1 194 | #endif // __CUDACC_VER__ >= 70000 195 | #endif // defined(__CUDACC__) 196 | #endif 197 | 198 | // ------------------------------------------------------------------ 199 | // Checks whether the compiler both supports and enables exceptions. 200 | // ------------------------------------------------------------------ 201 | #ifdef PHMAP_HAVE_EXCEPTIONS 202 | #error PHMAP_HAVE_EXCEPTIONS cannot be directly set. 203 | #elif defined(__clang__) 204 | #if defined(__EXCEPTIONS) && __has_feature(cxx_exceptions) 205 | #define PHMAP_HAVE_EXCEPTIONS 1 206 | #endif // defined(__EXCEPTIONS) && __has_feature(cxx_exceptions) 207 | #elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) && \ 208 | !(defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__cpp_exceptions)) && \ 209 | !(defined(_MSC_VER) && !defined(_CPPUNWIND)) 210 | #define PHMAP_HAVE_EXCEPTIONS 1 211 | #endif 212 | 213 | 214 | // ----------------------------------------------------------------------- 215 | // Checks whether the platform has an mmap(2) implementation as defined in 216 | // POSIX.1-2001. 217 | // ----------------------------------------------------------------------- 218 | #ifdef PHMAP_HAVE_MMAP 219 | #error PHMAP_HAVE_MMAP cannot be directly set 220 | #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ 221 | defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \ 222 | defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \ 223 | defined(__ASYLO__) 224 | #define PHMAP_HAVE_MMAP 1 225 | #endif 226 | 227 | // ----------------------------------------------------------------------- 228 | // Checks the endianness of the platform. 229 | // ----------------------------------------------------------------------- 230 | #if defined(PHMAP_IS_BIG_ENDIAN) 231 | #error "PHMAP_IS_BIG_ENDIAN cannot be directly set." 232 | #endif 233 | 234 | #if defined(PHMAP_IS_LITTLE_ENDIAN) 235 | #error "PHMAP_IS_LITTLE_ENDIAN cannot be directly set." 236 | #endif 237 | 238 | #if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ 239 | __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 240 | #define PHMAP_IS_LITTLE_ENDIAN 1 241 | #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ 242 | __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 243 | #define PHMAP_IS_BIG_ENDIAN 1 244 | #elif defined(_WIN32) 245 | #define PHMAP_IS_LITTLE_ENDIAN 1 246 | #else 247 | #error "phmap endian detection needs to be set up for your compiler" 248 | #endif 249 | 250 | #if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \ 251 | defined(__MAC_OS_X_VERSION_MIN_REQUIRED__) && \ 252 | __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400 253 | #define PHMAP_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 1 254 | #else 255 | #define PHMAP_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 0 256 | #endif 257 | 258 | // --------------------------------------------------------------------------- 259 | // Checks whether C++17 std::any is available by checking whether exists. 260 | // --------------------------------------------------------------------------- 261 | #ifdef PHMAP_HAVE_STD_ANY 262 | #error "PHMAP_HAVE_STD_ANY cannot be directly set." 263 | #endif 264 | 265 | #ifdef __has_include 266 | #if __has_include() && __cplusplus >= 201703L && \ 267 | !PHMAP_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 268 | #define PHMAP_HAVE_STD_ANY 1 269 | #endif 270 | #endif 271 | 272 | #ifdef PHMAP_HAVE_STD_OPTIONAL 273 | #error "PHMAP_HAVE_STD_OPTIONAL cannot be directly set." 274 | #endif 275 | 276 | #ifdef __has_include 277 | #if __has_include() && __cplusplus >= 201703L && \ 278 | !PHMAP_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 279 | #define PHMAP_HAVE_STD_OPTIONAL 1 280 | #endif 281 | #endif 282 | 283 | #ifdef PHMAP_HAVE_STD_VARIANT 284 | #error "PHMAP_HAVE_STD_VARIANT cannot be directly set." 285 | #endif 286 | 287 | #ifdef __has_include 288 | #if __has_include() && __cplusplus >= 201703L && \ 289 | !PHMAP_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 290 | #define PHMAP_HAVE_STD_VARIANT 1 291 | #endif 292 | #endif 293 | 294 | #ifdef PHMAP_HAVE_STD_STRING_VIEW 295 | #error "PHMAP_HAVE_STD_STRING_VIEW cannot be directly set." 296 | #endif 297 | 298 | #ifdef __has_include 299 | #if __has_include() && __cplusplus >= 201703L && \ 300 | (!defined(_MSC_VER) || _MSC_VER >= 1920) // vs2019 301 | #define PHMAP_HAVE_STD_STRING_VIEW 1 302 | #endif 303 | #endif 304 | 305 | // #pragma message(PHMAP_VAR_NAME_VALUE(_MSVC_LANG)) 306 | 307 | #if defined(_MSC_VER) && _MSC_VER >= 1910 && PHMAP_HAVE_CC17 308 | // #define PHMAP_HAVE_STD_ANY 1 309 | #define PHMAP_HAVE_STD_OPTIONAL 1 310 | #define PHMAP_HAVE_STD_VARIANT 1 311 | #if !defined(PHMAP_HAVE_STD_STRING_VIEW) && _MSC_VER >= 1920 312 | #define PHMAP_HAVE_STD_STRING_VIEW 1 313 | #endif 314 | #endif 315 | 316 | #if PHMAP_HAVE_CC17 317 | #define PHMAP_HAVE_SHARED_MUTEX 1 318 | #endif 319 | 320 | #ifndef PHMAP_HAVE_STD_STRING_VIEW 321 | #define PHMAP_HAVE_STD_STRING_VIEW 0 322 | #endif 323 | 324 | // In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION 325 | // SEH exception from emplace for variant when constructing the 326 | // struct can throw. This defeats some of variant_test and 327 | // variant_exception_safety_test. 328 | #if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG) 329 | #define PHMAP_INTERNAL_MSVC_2017_DBG_MODE 330 | #endif 331 | 332 | // --------------------------------------------------------------------------- 333 | // Checks whether wchar_t is treated as a native type 334 | // (MSVC: /Zc:wchar_t- treats wchar_t as unsigned short) 335 | // --------------------------------------------------------------------------- 336 | #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) 337 | #define PHMAP_HAS_NATIVE_WCHAR_T 338 | #endif 339 | 340 | // ----------------------------------------------------------------------------- 341 | // Sanitizer Attributes 342 | // ----------------------------------------------------------------------------- 343 | // 344 | // Sanitizer-related attributes are not "defined" in this file (and indeed 345 | // are not defined as such in any file). To utilize the following 346 | // sanitizer-related attributes within your builds, define the following macros 347 | // within your build using a `-D` flag, along with the given value for 348 | // `-fsanitize`: 349 | // 350 | // * `ADDRESS_SANITIZER` + `-fsanitize=address` (Clang, GCC 4.8) 351 | // * `MEMORY_SANITIZER` + `-fsanitize=memory` (Clang-only) 352 | // * `THREAD_SANITIZER + `-fsanitize=thread` (Clang, GCC 4.8+) 353 | // * `UNDEFINED_BEHAVIOR_SANITIZER` + `-fsanitize=undefined` (Clang, GCC 4.9+) 354 | // * `CONTROL_FLOW_INTEGRITY` + -fsanitize=cfi (Clang-only) 355 | // ----------------------------------------------------------------------------- 356 | 357 | // ----------------------------------------------------------------------------- 358 | // A function-like feature checking macro that is a wrapper around 359 | // `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a 360 | // nonzero constant integer if the attribute is supported or 0 if not. 361 | // 362 | // It evaluates to zero if `__has_attribute` is not defined by the compiler. 363 | // ----------------------------------------------------------------------------- 364 | #ifdef __has_attribute 365 | #define PHMAP_HAVE_ATTRIBUTE(x) __has_attribute(x) 366 | #else 367 | #define PHMAP_HAVE_ATTRIBUTE(x) 0 368 | #endif 369 | 370 | // ----------------------------------------------------------------------------- 371 | // A function-like feature checking macro that accepts C++11 style attributes. 372 | // It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6 373 | // (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't 374 | // find `__has_cpp_attribute`, will evaluate to 0. 375 | // ----------------------------------------------------------------------------- 376 | #if defined(__cplusplus) && defined(__has_cpp_attribute) 377 | #define PHMAP_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) 378 | #else 379 | #define PHMAP_HAVE_CPP_ATTRIBUTE(x) 0 380 | #endif 381 | 382 | // ----------------------------------------------------------------------------- 383 | // Function Attributes 384 | // ----------------------------------------------------------------------------- 385 | #if PHMAP_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__)) 386 | #define PHMAP_PRINTF_ATTRIBUTE(string_index, first_to_check) \ 387 | __attribute__((__format__(__printf__, string_index, first_to_check))) 388 | #define PHMAP_SCANF_ATTRIBUTE(string_index, first_to_check) \ 389 | __attribute__((__format__(__scanf__, string_index, first_to_check))) 390 | #else 391 | #define PHMAP_PRINTF_ATTRIBUTE(string_index, first_to_check) 392 | #define PHMAP_SCANF_ATTRIBUTE(string_index, first_to_check) 393 | #endif 394 | 395 | #if PHMAP_HAVE_ATTRIBUTE(always_inline) || \ 396 | (defined(__GNUC__) && !defined(__clang__)) 397 | #define PHMAP_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) 398 | #define PHMAP_HAVE_ATTRIBUTE_ALWAYS_INLINE 1 399 | #else 400 | #define PHMAP_ATTRIBUTE_ALWAYS_INLINE 401 | #endif 402 | 403 | #if !defined(__INTEL_COMPILER) && (PHMAP_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__))) 404 | #define PHMAP_ATTRIBUTE_NOINLINE __attribute__((noinline)) 405 | #define PHMAP_HAVE_ATTRIBUTE_NOINLINE 1 406 | #else 407 | #define PHMAP_ATTRIBUTE_NOINLINE 408 | #endif 409 | 410 | #if PHMAP_HAVE_ATTRIBUTE(disable_tail_calls) 411 | #define PHMAP_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 412 | #define PHMAP_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls)) 413 | #elif defined(__GNUC__) && !defined(__clang__) 414 | #define PHMAP_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 415 | #define PHMAP_ATTRIBUTE_NO_TAIL_CALL \ 416 | __attribute__((optimize("no-optimize-sibling-calls"))) 417 | #else 418 | #define PHMAP_ATTRIBUTE_NO_TAIL_CALL 419 | #define PHMAP_HAVE_ATTRIBUTE_NO_TAIL_CALL 0 420 | #endif 421 | 422 | #if (PHMAP_HAVE_ATTRIBUTE(weak) || \ 423 | (defined(__GNUC__) && !defined(__clang__))) && \ 424 | !(defined(__llvm__) && defined(_WIN32)) 425 | #undef PHMAP_ATTRIBUTE_WEAK 426 | #define PHMAP_ATTRIBUTE_WEAK __attribute__((weak)) 427 | #define PHMAP_HAVE_ATTRIBUTE_WEAK 1 428 | #else 429 | #define PHMAP_ATTRIBUTE_WEAK 430 | #define PHMAP_HAVE_ATTRIBUTE_WEAK 0 431 | #endif 432 | 433 | #if PHMAP_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__)) 434 | #define PHMAP_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index))) 435 | #else 436 | #define PHMAP_ATTRIBUTE_NONNULL(...) 437 | #endif 438 | 439 | #if PHMAP_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__)) 440 | #define PHMAP_ATTRIBUTE_NORETURN __attribute__((noreturn)) 441 | #elif defined(_MSC_VER) 442 | #define PHMAP_ATTRIBUTE_NORETURN __declspec(noreturn) 443 | #else 444 | #define PHMAP_ATTRIBUTE_NORETURN 445 | #endif 446 | 447 | #if defined(__GNUC__) && defined(ADDRESS_SANITIZER) 448 | #define PHMAP_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) 449 | #else 450 | #define PHMAP_ATTRIBUTE_NO_SANITIZE_ADDRESS 451 | #endif 452 | 453 | #if defined(__GNUC__) && defined(MEMORY_SANITIZER) 454 | #define PHMAP_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) 455 | #else 456 | #define PHMAP_ATTRIBUTE_NO_SANITIZE_MEMORY 457 | #endif 458 | 459 | #if defined(__GNUC__) && defined(THREAD_SANITIZER) 460 | #define PHMAP_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) 461 | #else 462 | #define PHMAP_ATTRIBUTE_NO_SANITIZE_THREAD 463 | #endif 464 | 465 | #if defined(__GNUC__) && \ 466 | (defined(UNDEFINED_BEHAVIOR_SANITIZER) || defined(ADDRESS_SANITIZER)) 467 | #define PHMAP_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ 468 | __attribute__((no_sanitize("undefined"))) 469 | #else 470 | #define PHMAP_ATTRIBUTE_NO_SANITIZE_UNDEFINED 471 | #endif 472 | 473 | #if defined(__GNUC__) && defined(CONTROL_FLOW_INTEGRITY) 474 | #define PHMAP_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) 475 | #else 476 | #define PHMAP_ATTRIBUTE_NO_SANITIZE_CFI 477 | #endif 478 | 479 | #if defined(__GNUC__) && defined(SAFESTACK_SANITIZER) 480 | #define PHMAP_ATTRIBUTE_NO_SANITIZE_SAFESTACK \ 481 | __attribute__((no_sanitize("safe-stack"))) 482 | #else 483 | #define PHMAP_ATTRIBUTE_NO_SANITIZE_SAFESTACK 484 | #endif 485 | 486 | #if PHMAP_HAVE_ATTRIBUTE(returns_nonnull) || \ 487 | (defined(__GNUC__) && \ 488 | (__GNUC__ > 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) && \ 489 | !defined(__clang__)) 490 | #define PHMAP_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) 491 | #else 492 | #define PHMAP_ATTRIBUTE_RETURNS_NONNULL 493 | #endif 494 | 495 | #ifdef PHMAP_HAVE_ATTRIBUTE_SECTION 496 | #error PHMAP_HAVE_ATTRIBUTE_SECTION cannot be directly set 497 | #elif (PHMAP_HAVE_ATTRIBUTE(section) || \ 498 | (defined(__GNUC__) && !defined(__clang__))) && \ 499 | !defined(__APPLE__) && PHMAP_HAVE_ATTRIBUTE_WEAK 500 | #define PHMAP_HAVE_ATTRIBUTE_SECTION 1 501 | #ifndef PHMAP_ATTRIBUTE_SECTION 502 | #define PHMAP_ATTRIBUTE_SECTION(name) \ 503 | __attribute__((section(#name))) __attribute__((noinline)) 504 | #endif 505 | #ifndef PHMAP_ATTRIBUTE_SECTION_VARIABLE 506 | #define PHMAP_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name))) 507 | #endif 508 | #ifndef PHMAP_DECLARE_ATTRIBUTE_SECTION_VARS 509 | #define PHMAP_DECLARE_ATTRIBUTE_SECTION_VARS(name) \ 510 | extern char __start_##name[] PHMAP_ATTRIBUTE_WEAK; \ 511 | extern char __stop_##name[] PHMAP_ATTRIBUTE_WEAK 512 | #endif 513 | #ifndef PHMAP_DEFINE_ATTRIBUTE_SECTION_VARS 514 | #define PHMAP_INIT_ATTRIBUTE_SECTION_VARS(name) 515 | #define PHMAP_DEFINE_ATTRIBUTE_SECTION_VARS(name) 516 | #endif 517 | #define PHMAP_ATTRIBUTE_SECTION_START(name) \ 518 | (reinterpret_cast(__start_##name)) 519 | #define PHMAP_ATTRIBUTE_SECTION_STOP(name) \ 520 | (reinterpret_cast(__stop_##name)) 521 | #else // !PHMAP_HAVE_ATTRIBUTE_SECTION 522 | #define PHMAP_HAVE_ATTRIBUTE_SECTION 0 523 | #define PHMAP_ATTRIBUTE_SECTION(name) 524 | #define PHMAP_ATTRIBUTE_SECTION_VARIABLE(name) 525 | #define PHMAP_INIT_ATTRIBUTE_SECTION_VARS(name) 526 | #define PHMAP_DEFINE_ATTRIBUTE_SECTION_VARS(name) 527 | #define PHMAP_DECLARE_ATTRIBUTE_SECTION_VARS(name) 528 | #define PHMAP_ATTRIBUTE_SECTION_START(name) (reinterpret_cast(0)) 529 | #define PHMAP_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast(0)) 530 | #endif // PHMAP_ATTRIBUTE_SECTION 531 | 532 | #if PHMAP_HAVE_ATTRIBUTE(force_align_arg_pointer) || \ 533 | (defined(__GNUC__) && !defined(__clang__)) 534 | #if defined(__i386__) 535 | #define PHMAP_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \ 536 | __attribute__((force_align_arg_pointer)) 537 | #define PHMAP_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) 538 | #elif defined(__x86_64__) 539 | #define PHMAP_REQUIRE_STACK_ALIGN_TRAMPOLINE (1) 540 | #define PHMAP_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC 541 | #else // !__i386__ && !__x86_64 542 | #define PHMAP_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) 543 | #define PHMAP_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC 544 | #endif // __i386__ 545 | #else 546 | #define PHMAP_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC 547 | #define PHMAP_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) 548 | #endif 549 | 550 | #if PHMAP_HAVE_ATTRIBUTE(nodiscard) 551 | #define PHMAP_MUST_USE_RESULT [[nodiscard]] 552 | #elif defined(__clang__) && PHMAP_HAVE_ATTRIBUTE(warn_unused_result) 553 | #define PHMAP_MUST_USE_RESULT __attribute__((warn_unused_result)) 554 | #else 555 | #define PHMAP_MUST_USE_RESULT 556 | #endif 557 | 558 | #if PHMAP_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__)) 559 | #define PHMAP_ATTRIBUTE_HOT __attribute__((hot)) 560 | #else 561 | #define PHMAP_ATTRIBUTE_HOT 562 | #endif 563 | 564 | #if PHMAP_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__)) 565 | #define PHMAP_ATTRIBUTE_COLD __attribute__((cold)) 566 | #else 567 | #define PHMAP_ATTRIBUTE_COLD 568 | #endif 569 | 570 | #if defined(__clang__) 571 | #if PHMAP_HAVE_CPP_ATTRIBUTE(clang::reinitializes) 572 | #define PHMAP_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] 573 | #else 574 | #define PHMAP_ATTRIBUTE_REINITIALIZES 575 | #endif 576 | #else 577 | #define PHMAP_ATTRIBUTE_REINITIALIZES 578 | #endif 579 | 580 | #if PHMAP_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__)) 581 | #undef PHMAP_ATTRIBUTE_UNUSED 582 | #define PHMAP_ATTRIBUTE_UNUSED __attribute__((__unused__)) 583 | #else 584 | #define PHMAP_ATTRIBUTE_UNUSED 585 | #endif 586 | 587 | #if PHMAP_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__)) 588 | #define PHMAP_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec"))) 589 | #else 590 | #define PHMAP_ATTRIBUTE_INITIAL_EXEC 591 | #endif 592 | 593 | #if PHMAP_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__)) 594 | #define PHMAP_ATTRIBUTE_PACKED __attribute__((__packed__)) 595 | #else 596 | #define PHMAP_ATTRIBUTE_PACKED 597 | #endif 598 | 599 | #if PHMAP_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) 600 | #define PHMAP_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) 601 | #else 602 | #define PHMAP_ATTRIBUTE_FUNC_ALIGN(bytes) 603 | #endif 604 | 605 | // ---------------------------------------------------------------------- 606 | // Figure out SSE support 607 | // ---------------------------------------------------------------------- 608 | #ifndef PHMAP_HAVE_SSE2 609 | #if defined(__SSE2__) || \ 610 | (defined(_MSC_VER) && \ 611 | (defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2))) 612 | #define PHMAP_HAVE_SSE2 1 613 | #else 614 | #define PHMAP_HAVE_SSE2 0 615 | #endif 616 | #endif 617 | 618 | #ifndef PHMAP_HAVE_SSSE3 619 | #if defined(__SSSE3__) || defined(__AVX2__) 620 | #define PHMAP_HAVE_SSSE3 1 621 | #else 622 | #define PHMAP_HAVE_SSSE3 0 623 | #endif 624 | #endif 625 | 626 | #if PHMAP_HAVE_SSSE3 && !PHMAP_HAVE_SSE2 627 | #error "Bad configuration!" 628 | #endif 629 | 630 | #if PHMAP_HAVE_SSE2 631 | #include 632 | #endif 633 | 634 | #if PHMAP_HAVE_SSSE3 635 | #include 636 | #endif 637 | 638 | 639 | // ---------------------------------------------------------------------- 640 | // constexpr if 641 | // ---------------------------------------------------------------------- 642 | #if PHMAP_HAVE_CC17 643 | #define PHMAP_IF_CONSTEXPR(expr) if constexpr ((expr)) 644 | #else 645 | #define PHMAP_IF_CONSTEXPR(expr) if ((expr)) 646 | #endif 647 | 648 | // ---------------------------------------------------------------------- 649 | // base/macros.h 650 | // ---------------------------------------------------------------------- 651 | 652 | // PHMAP_ARRAYSIZE() 653 | // 654 | // Returns the number of elements in an array as a compile-time constant, which 655 | // can be used in defining new arrays. If you use this macro on a pointer by 656 | // mistake, you will get a compile-time error. 657 | #define PHMAP_ARRAYSIZE(array) \ 658 | (sizeof(::phmap::macros_internal::ArraySizeHelper(array))) 659 | 660 | namespace phmap { 661 | namespace macros_internal { 662 | // Note: this internal template function declaration is used by PHMAP_ARRAYSIZE. 663 | // The function doesn't need a definition, as we only use its type. 664 | template 665 | auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N]; 666 | } // namespace macros_internal 667 | } // namespace phmap 668 | 669 | // TODO(zhangxy): Use c++17 standard [[fallthrough]] macro, when supported. 670 | #if defined(__clang__) && defined(__has_warning) 671 | #if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") 672 | #define PHMAP_FALLTHROUGH_INTENDED [[clang::fallthrough]] 673 | #endif 674 | #elif defined(__GNUC__) && __GNUC__ >= 7 675 | #define PHMAP_FALLTHROUGH_INTENDED [[gnu::fallthrough]] 676 | #endif 677 | 678 | #ifndef PHMAP_FALLTHROUGH_INTENDED 679 | #define PHMAP_FALLTHROUGH_INTENDED \ 680 | do { } while (0) 681 | #endif 682 | 683 | // PHMAP_DEPRECATED() 684 | // 685 | // Marks a deprecated class, struct, enum, function, method and variable 686 | // declarations. The macro argument is used as a custom diagnostic message (e.g. 687 | // suggestion of a better alternative). 688 | // 689 | // Example: 690 | // 691 | // class PHMAP_DEPRECATED("Use Bar instead") Foo {...}; 692 | // PHMAP_DEPRECATED("Use Baz instead") void Bar() {...} 693 | // 694 | // Every usage of a deprecated entity will trigger a warning when compiled with 695 | // clang's `-Wdeprecated-declarations` option. This option is turned off by 696 | // default, but the warnings will be reported by clang-tidy. 697 | #if defined(__clang__) && __cplusplus >= 201103L 698 | #define PHMAP_DEPRECATED(message) __attribute__((deprecated(message))) 699 | #endif 700 | 701 | #ifndef PHMAP_DEPRECATED 702 | #define PHMAP_DEPRECATED(message) 703 | #endif 704 | 705 | // PHMAP_BAD_CALL_IF() 706 | // 707 | // Used on a function overload to trap bad calls: any call that matches the 708 | // overload will cause a compile-time error. This macro uses a clang-specific 709 | // "enable_if" attribute, as described at 710 | // http://clang.llvm.org/docs/AttributeReference.html#enable-if 711 | // 712 | // Overloads which use this macro should be bracketed by 713 | // `#ifdef PHMAP_BAD_CALL_IF`. 714 | // 715 | // Example: 716 | // 717 | // int isdigit(int c); 718 | // #ifdef PHMAP_BAD_CALL_IF 719 | // int isdigit(int c) 720 | // PHMAP_BAD_CALL_IF(c <= -1 || c > 255, 721 | // "'c' must have the value of an unsigned char or EOF"); 722 | // #endif // PHMAP_BAD_CALL_IF 723 | 724 | #if defined(__clang__) 725 | #if __has_attribute(enable_if) 726 | #define PHMAP_BAD_CALL_IF(expr, msg) \ 727 | __attribute__((enable_if(expr, "Bad call trap"), unavailable(msg))) 728 | #endif 729 | #endif 730 | 731 | // PHMAP_ASSERT() 732 | // 733 | // In C++11, `assert` can't be used portably within constexpr functions. 734 | // PHMAP_ASSERT functions as a runtime assert but works in C++11 constexpr 735 | // functions. Example: 736 | // 737 | // constexpr double Divide(double a, double b) { 738 | // return PHMAP_ASSERT(b != 0), a / b; 739 | // } 740 | // 741 | // This macro is inspired by 742 | // https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/ 743 | #if defined(NDEBUG) 744 | #define PHMAP_ASSERT(expr) (false ? (void)(expr) : (void)0) 745 | #else 746 | #define PHMAP_ASSERT(expr) \ 747 | (PHMAP_PREDICT_TRUE((expr)) ? (void)0 \ 748 | : [] { assert(false && #expr); }()) // NOLINT 749 | #endif 750 | 751 | #ifdef PHMAP_HAVE_EXCEPTIONS 752 | #define PHMAP_INTERNAL_TRY try 753 | #define PHMAP_INTERNAL_CATCH_ANY catch (...) 754 | #define PHMAP_INTERNAL_RETHROW do { throw; } while (false) 755 | #else // PHMAP_HAVE_EXCEPTIONS 756 | #define PHMAP_INTERNAL_TRY if (true) 757 | #define PHMAP_INTERNAL_CATCH_ANY else if (false) 758 | #define PHMAP_INTERNAL_RETHROW do {} while (false) 759 | #endif // PHMAP_HAVE_EXCEPTIONS 760 | 761 | 762 | #endif // phmap_config_h_guard_ 763 | -------------------------------------------------------------------------------- /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_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/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 : public phmap_unary_function 191 | { 192 | inline size_t operator()(signed char val) const noexcept 193 | { return static_cast(val); } 194 | }; 195 | 196 | template <> 197 | struct Hash : public phmap_unary_function 198 | { 199 | inline size_t operator()(unsigned char val) const noexcept 200 | { return static_cast(val); } 201 | }; 202 | 203 | #ifdef PHMAP_HAS_NATIVE_WCHAR_T 204 | template <> 205 | struct Hash : public phmap_unary_function 206 | { 207 | inline size_t operator()(wchar_t val) const noexcept 208 | { return static_cast(val); } 209 | }; 210 | #endif 211 | 212 | template <> 213 | struct Hash : public phmap_unary_function 214 | { 215 | inline size_t operator()(int16_t val) const noexcept 216 | { return static_cast(val); } 217 | }; 218 | 219 | template <> 220 | struct Hash : public phmap_unary_function 221 | { 222 | inline size_t operator()(uint16_t val) const noexcept 223 | { return static_cast(val); } 224 | }; 225 | 226 | template <> 227 | struct Hash : public phmap_unary_function 228 | { 229 | inline size_t operator()(int32_t val) const noexcept 230 | { return static_cast(val); } 231 | }; 232 | 233 | template <> 234 | struct Hash : public phmap_unary_function 235 | { 236 | inline size_t operator()(uint32_t val) const noexcept 237 | { return static_cast(val); } 238 | }; 239 | 240 | template <> 241 | struct Hash : public phmap_unary_function 242 | { 243 | inline size_t operator()(int64_t val) const noexcept 244 | { return fold_if_needed()(static_cast(val)); } 245 | }; 246 | 247 | template <> 248 | struct Hash : public phmap_unary_function 249 | { 250 | inline size_t operator()(uint64_t val) const noexcept 251 | { return fold_if_needed()(val); } 252 | }; 253 | 254 | template <> 255 | struct Hash : public phmap_unary_function 256 | { 257 | inline size_t operator()(float val) const noexcept 258 | { 259 | // -0.0 and 0.0 should return same hash 260 | uint32_t *as_int = reinterpret_cast(&val); 261 | return (val == 0) ? static_cast(0) : 262 | static_cast(*as_int); 263 | } 264 | }; 265 | 266 | template <> 267 | struct Hash : public phmap_unary_function 268 | { 269 | inline size_t operator()(double val) const noexcept 270 | { 271 | // -0.0 and 0.0 should return same hash 272 | uint64_t *as_int = reinterpret_cast(&val); 273 | return (val == 0) ? static_cast(0) : 274 | fold_if_needed()(*as_int); 275 | } 276 | }; 277 | 278 | #endif 279 | 280 | #if defined(_MSC_VER) 281 | # define PHMAP_HASH_ROTL32(x, r) _rotl(x,r) 282 | #else 283 | # define PHMAP_HASH_ROTL32(x, r) (x << r) | (x >> (32 - r)) 284 | #endif 285 | 286 | 287 | template struct Combiner 288 | { 289 | H operator()(H seed, size_t value); 290 | }; 291 | 292 | template struct Combiner 293 | { 294 | H operator()(H h1, size_t k1) 295 | { 296 | #if 1 297 | // Copyright 2005-2014 Daniel James. 298 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 299 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 300 | 301 | const uint32_t c1 = 0xcc9e2d51; 302 | const uint32_t c2 = 0x1b873593; 303 | 304 | k1 *= c1; 305 | k1 = PHMAP_HASH_ROTL32(k1,15); 306 | k1 *= c2; 307 | 308 | h1 ^= k1; 309 | h1 = PHMAP_HASH_ROTL32(h1,13); 310 | h1 = h1*5+0xe6546b64; 311 | 312 | return h1; 313 | #else 314 | return h1 ^ (k1 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2)); 315 | #endif 316 | } 317 | }; 318 | 319 | template struct Combiner 320 | { 321 | H operator()(H h, size_t k) 322 | { 323 | #if 1 324 | // Copyright 2005-2014 Daniel James. 325 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 326 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 327 | const uint64_t m = (uint64_t(0xc6a4a793) << 32) + 0x5bd1e995; 328 | const int r = 47; 329 | 330 | k *= m; 331 | k ^= k >> r; 332 | k *= m; 333 | 334 | h ^= k; 335 | h *= m; 336 | 337 | // Completely arbitrary number, to prevent 0's 338 | // from hashing to 0. 339 | h += 0xe6546b64; 340 | 341 | return h; 342 | #else 343 | return h ^ (k + size_t(0xc6a4a7935bd1e995) + (h << 6) + (h >> 2)); 344 | #endif 345 | } 346 | }; 347 | 348 | // define HashState to combine member hashes... see example below 349 | // ----------------------------------------------------------------------------- 350 | template 351 | class HashStateBase { 352 | public: 353 | template 354 | static H combine(H state, const T& value, const Ts&... values); 355 | 356 | static H combine(H state) { return state; } 357 | }; 358 | 359 | template 360 | template 361 | H HashStateBase::combine(H seed, const T& v, const Ts&... vs) 362 | { 363 | return HashStateBase::combine(Combiner()( 364 | seed, phmap::Hash()(v)), 365 | vs...); 366 | } 367 | 368 | using HashState = HashStateBase; 369 | 370 | // ----------------------------------------------------------------------------- 371 | 372 | #if !defined(PHMAP_USE_ABSL_HASH) 373 | 374 | // define Hash for std::pair 375 | // ------------------------- 376 | template 377 | struct Hash> { 378 | size_t operator()(std::pair const& p) const noexcept { 379 | return phmap::HashState().combine(phmap::Hash()(p.first), p.second); 380 | } 381 | }; 382 | 383 | // define Hash for std::tuple 384 | // -------------------------- 385 | template 386 | struct Hash> { 387 | size_t operator()(std::tuple const& t) const noexcept { 388 | size_t seed = 0; 389 | return _hash_helper(seed, t); 390 | } 391 | 392 | private: 393 | template 394 | typename std::enable_if::value, size_t>::type 395 | _hash_helper(size_t seed, const TUP &) const noexcept { return seed; } 396 | 397 | template 398 | typename std::enable_if::value, size_t>::type 399 | _hash_helper(size_t seed, const TUP &t) const noexcept { 400 | const auto &el = std::get(t); 401 | using el_type = typename std::remove_cv::type>::type; 402 | seed = Combiner()(seed, phmap::Hash()(el)); 403 | return _hash_helper(seed, t); 404 | } 405 | }; 406 | 407 | 408 | #endif 409 | 410 | 411 | } // namespace phmap 412 | 413 | #ifdef _MSC_VER 414 | #pragma warning(pop) 415 | #endif 416 | 417 | #endif // phmap_utils_h_guard_ 418 | -------------------------------------------------------------------------------- /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/ue4.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "enums.h" 5 | #include "util.h" 6 | #include "parallel_hashmap\phmap.h" 7 | #include "parallel_hashmap\phmap_utils.h" 8 | 9 | class UAllocator 10 | { 11 | public: 12 | void* structPtr = nullptr; 13 | 14 | private: 15 | size_t totalSize = 0; 16 | size_t padding = 0; 17 | size_t lastSize = 0; 18 | 19 | template 20 | void add(T Src) 21 | { 22 | constexpr auto Size = sizeof(T); 23 | 24 | totalSize += Size; 25 | 26 | structPtr = realloc(structPtr, totalSize); 27 | if (structPtr) 28 | { 29 | memcpy((void*)(reinterpret_cast(structPtr) + padding), &Src, Size); 30 | } 31 | 32 | // printf("Size: %d, totalSize: %d, padding: %d\n", Size, totalSize, padding); 33 | 34 | padding += Size; 35 | lastSize = Size; 36 | } 37 | 38 | template 39 | [[nodiscard]] constexpr void* Create() const 40 | { 41 | return (void*)((uintptr_t)structPtr + padding - lastSize); 42 | } 43 | 44 | public: 45 | template 46 | void* Create(T retValue, Rest... params) 47 | { 48 | add(retValue); 49 | 50 | return Create<>(params...); 51 | } 52 | 53 | // Free memory when we get out of the scope 54 | /*~UAllocator() 55 | { 56 | free(structPtr); 57 | }*/ 58 | }; 59 | 60 | template 61 | struct TArray 62 | { 63 | friend struct FString; 64 | 65 | public: 66 | T* Data; 67 | int32_t Count; 68 | int32_t Max; 69 | 70 | TArray() 71 | { 72 | Data = nullptr; 73 | Count = Max = 0; 74 | }; 75 | 76 | TArray(unsigned int ReserveAmount) 77 | { 78 | Data = nullptr; 79 | Count = Max = 0; 80 | Reserve(ReserveAmount); 81 | }; 82 | 83 | int Num() const 84 | { 85 | return Count; 86 | }; 87 | 88 | T& operator[](int i) 89 | { 90 | return Data[i]; 91 | }; 92 | 93 | const T& operator[](int i) const 94 | { 95 | return Data[i]; 96 | }; 97 | 98 | bool IsValidIndex(int i) const 99 | { 100 | return i < Num(); 101 | } 102 | 103 | void Reserve(unsigned int Amount) 104 | { 105 | if (Data) 106 | { 107 | Data = static_cast(realloc(Data, sizeof(T) * (Count + Amount))); 108 | } 109 | else 110 | { 111 | Data = static_cast(malloc(sizeof(T) * (Count + Amount))); 112 | } 113 | 114 | Max = Count + Amount; 115 | } 116 | 117 | void Add(T InputData) 118 | { 119 | if (Max <= Count) 120 | { 121 | if (Data) 122 | { 123 | Data = static_cast(realloc(Data, sizeof(T) * (Count + 1))); 124 | } 125 | else 126 | { 127 | Data = static_cast(malloc(sizeof(T) * (Count + 1))); 128 | } 129 | 130 | Data[Count++] = InputData; 131 | Max = Count; 132 | } 133 | else 134 | { 135 | Data[Count++] = InputData; 136 | } 137 | }; 138 | 139 | void Delete() 140 | { 141 | delete Data; 142 | }; 143 | 144 | auto ToVector() -> std::vector 145 | { 146 | std::vector Vector; 147 | for (int i = 0; i < Count; i++) 148 | { 149 | Vector.push_back(Data[i]); 150 | } 151 | 152 | return Vector; 153 | } 154 | }; 155 | 156 | template 157 | class TPair 158 | { 159 | public: 160 | KeyType Key; 161 | ValueType Value; 162 | }; 163 | 164 | struct FString : private TArray 165 | { 166 | FString() {}; 167 | 168 | FString(const wchar_t* other) 169 | { 170 | Max = Count = *other ? (int32_t)std::wcslen(other) + 1 : 0; 171 | 172 | if (Count) 173 | { 174 | Data = const_cast(other); 175 | } 176 | } 177 | 178 | bool IsValid() const 179 | { 180 | return Data != nullptr; 181 | } 182 | 183 | const wchar_t* ToWString() const 184 | { 185 | return Data; 186 | } 187 | 188 | std::string ToString() const 189 | { 190 | auto length = std::wcslen(Data); 191 | 192 | std::string str(length, '\0'); 193 | 194 | std::use_facet>(std::locale()).narrow(Data, Data + length, '?', &str[0]); 195 | 196 | return str; 197 | } 198 | }; 199 | 200 | // FName::ToString 201 | inline void (*FNameToString)(const void* _this, FString& out); 202 | 203 | struct FName 204 | { 205 | mutable uint32_t ComparisonIndex; 206 | mutable uint32_t DisplayIndex; 207 | 208 | FName() = default; 209 | 210 | explicit FName(int64_t name) 211 | { 212 | DisplayIndex = (name & 0xFFFFFFFF00000000LL) >> 32; 213 | ComparisonIndex = (name & 0xFFFFFFFFLL); 214 | }; 215 | 216 | bool operator==(FName n) const 217 | { 218 | return ComparisonIndex == n.ComparisonIndex; 219 | } 220 | 221 | auto ToString() const 222 | { 223 | FString temp; 224 | FNameToString(this, temp); 225 | 226 | std::string ret(temp.ToString()); 227 | 228 | return ret; 229 | } 230 | 231 | auto ToWString() const 232 | { 233 | FString temp; 234 | FNameToString(this, temp); 235 | 236 | std::wstring ret(temp.ToWString()); 237 | 238 | return ret; 239 | } 240 | 241 | friend size_t hash_value(const FName& p) 242 | { 243 | return phmap::HashState().combine(0, p.ComparisonIndex, p.ComparisonIndex / 3); 244 | } 245 | }; 246 | 247 | template 248 | class TEnumAsByte 249 | { 250 | public: 251 | TEnumAsByte() 252 | { 253 | } 254 | 255 | TEnumAsByte(TEnum _value) 256 | : value(static_cast(_value)) 257 | { 258 | } 259 | 260 | explicit TEnumAsByte(int32_t _value) 261 | : value(static_cast(_value)) 262 | { 263 | } 264 | 265 | explicit TEnumAsByte(uint8_t _value) 266 | : value(_value) 267 | { 268 | } 269 | 270 | operator TEnum() const 271 | { 272 | return static_cast(value); 273 | } 274 | 275 | TEnum GetValue() const 276 | { 277 | return static_cast(value); 278 | } 279 | 280 | private: 281 | uint8_t value; 282 | }; 283 | 284 | class UObject; 285 | 286 | struct FUObjectItem 287 | { 288 | UObject* Object; 289 | int32_t Flags; 290 | int32_t ClusterIndex; 291 | int32_t SerialNumber; 292 | }; 293 | 294 | struct GlobalObjects 295 | { 296 | enum 297 | { 298 | NumElementsPerChunk = 64 * 1024, 299 | }; 300 | 301 | FUObjectItem** Objects; 302 | FUObjectItem* PreAllocatedObjects; 303 | int32_t MaxElements; 304 | int32_t NumElements; 305 | int32_t MaxChunks; 306 | int32_t NumChunks; 307 | 308 | UObject* GetByIndex(int32_t Index) const 309 | { 310 | int ChunkIndex = Index / NumElementsPerChunk; 311 | int WithinChunkIndex = Index % NumElementsPerChunk; 312 | 313 | if ( 314 | Index < NumElements && Index >= 0 && ChunkIndex < NumChunks && Index < MaxElements) 315 | { 316 | auto Chunk = Objects[ChunkIndex]; 317 | 318 | if (Chunk) 319 | return (Chunk + WithinChunkIndex)->Object; 320 | } 321 | 322 | return nullptr; 323 | } 324 | 325 | bool TryFindObject(std::string startOfName, UObject& out); 326 | bool TryFindObjectByName(std::string name, UObject& out); 327 | }; 328 | 329 | inline struct GlobalObjects* GObjects; 330 | inline struct FNamePool* GNames; 331 | 332 | struct FPointer 333 | { 334 | uintptr_t Dummy; 335 | }; 336 | 337 | // UObjectGlobals::StaticLoadObject_Internal 338 | inline UObject* (*StaticLoadObject_Internal)(void* Class, void* Outer, const TCHAR* Name, const TCHAR* Filename, uint32_t LoadFlags, void* Sandbox, bool bAllowObjectReconciliation, void* InSerializeContext); 339 | 340 | // UObject::ProcessEvent 341 | static void* (*ProcessEventR)(void*, void*, void*); 342 | 343 | // GetNamePool 344 | inline FNamePool* (*GetNamePool)(); 345 | 346 | __forceinline std::string GetNameSafe(UObject* Object); 347 | 348 | class UObject 349 | { 350 | public: 351 | FPointer VTableObject; 352 | DWORD ObjectFlags; 353 | DWORD InternalIndex; 354 | class UClass* Class; 355 | FName NamePrivate; 356 | UObject* Outer; 357 | 358 | auto GetVTableObject() 359 | { 360 | return *reinterpret_cast(this); 361 | } 362 | 363 | auto ProcessEvent(void* fn, void* params) 364 | { 365 | ProcessEventR(this, fn, params); 366 | } 367 | 368 | template 369 | FORCEINLINE ReturnType Call(UObject* function, First&& firstParam, Rest&&... params) 370 | { 371 | ReturnType RetInstance {}; 372 | 373 | UAllocator alloc {}; 374 | 375 | auto ret = (ReturnType*)alloc.Create(std::forward(firstParam), 376 | std::forward(params)..., 377 | RetInstance); 378 | 379 | ProcessEvent(function, alloc.structPtr); 380 | 381 | return ret; 382 | } 383 | 384 | template 385 | static T FindObject(char const* name, bool ends_with = false, int toSkip = 0) 386 | { 387 | for (auto i = 0x0; i < GObjects->NumElements; ++i) 388 | { 389 | auto object = GObjects->GetByIndex(i); 390 | if (object == nullptr) 391 | { 392 | continue; 393 | } 394 | 395 | std::string objectFullName = object->GetFullName(); 396 | 397 | if (!ends_with) 398 | { 399 | if (objectFullName.starts_with(name)) 400 | { 401 | if (toSkip > 0) 402 | { 403 | toSkip--; 404 | } 405 | else 406 | { 407 | return reinterpret_cast(object); 408 | } 409 | } 410 | } 411 | else 412 | { 413 | if (objectFullName.ends_with(name)) 414 | { 415 | return reinterpret_cast(object); 416 | } 417 | } 418 | } 419 | return nullptr; 420 | } 421 | 422 | auto IsValid() const -> bool 423 | { 424 | return (!Util::IsBadReadPtr((void*)this)); 425 | } 426 | 427 | static UObject* StaticLoadObjectEasy(UClass* inClass, const wchar_t* inName, UObject* inOuter = nullptr) 428 | { 429 | return StaticLoadObject_Internal(inClass, inOuter, inName, nullptr, 0, nullptr, false, nullptr); 430 | } 431 | 432 | template 433 | bool IsA() const; 434 | 435 | template 436 | Base Cast() const 437 | { 438 | return Base(this); 439 | } 440 | 441 | bool IsA(UClass* cmp) const; 442 | 443 | std::string GetCPPName(); 444 | 445 | auto GetName() 446 | { 447 | return NamePrivate.ToString(); 448 | } 449 | 450 | std::string GetFullName() 451 | { 452 | std::string temp; 453 | 454 | for (auto outer = Outer; outer; outer = outer->Outer) 455 | { 456 | temp = GetNameSafe(outer) + "." + temp; 457 | } 458 | 459 | temp = GetNameSafe(reinterpret_cast(Class)) + " " + temp + GetNameSafe(this); 460 | return temp; 461 | } 462 | 463 | static class UClass* StaticClass() 464 | { 465 | static auto c = FindObject("Class /Script/CoreUObject.Object"); 466 | return c; 467 | } 468 | }; 469 | 470 | __forceinline std::string GetNameSafe(UObject* Object) 471 | { 472 | if (Object == nullptr) 473 | return "None"; 474 | else 475 | return Object->GetName(); 476 | } 477 | 478 | class FField; 479 | 480 | class FFieldVariant 481 | { 482 | public: 483 | union FFieldObjectUnion 484 | { 485 | FField* Field; 486 | UObject* Object; 487 | } Container; 488 | }; 489 | 490 | enum class FFieldClassID : uint64_t 491 | { 492 | Int8 = 1llu << 1, 493 | Byte = 1llu << 6, 494 | Int = 1llu << 7, 495 | Float = 1llu << 8, 496 | UInt64 = 1llu << 9, 497 | Class = 1llu << 10, 498 | UInt32 = 1llu << 11, 499 | Interface = 1llu << 12, 500 | Name = 1llu << 13, 501 | String = 1llu << 14, 502 | Object = 1llu << 16, 503 | Bool = 1llu << 17, 504 | UInt16 = 1llu << 18, 505 | Struct = 1llu << 20, 506 | Array = 1llu << 21, 507 | Int64 = 1llu << 22, 508 | Delegate = 1llu << 23, 509 | SoftObject = 1llu << 27, 510 | LazyObject = 1llu << 28, 511 | WeakObject = 1llu << 29, 512 | Text = 1llu << 30, 513 | Int16 = 1llu << 31, 514 | Double = 1llu << 32, 515 | SoftClass = 1llu << 33, 516 | Map = 1llu << 46, 517 | Set = 1llu << 47, 518 | Enum = 1llu << 48, 519 | MulticastInlineDelegate = 1llu << 50, 520 | MulticastSparseDelegate = 1llu << 51, 521 | ObjectPointer = 1llu << 53 522 | }; 523 | 524 | class FFieldClass 525 | { 526 | public: 527 | FName Name; 528 | FFieldClassID Id; 529 | uint64_t CastFlags; 530 | EClassFlags ClassFlags; 531 | FFieldClass* SuperClass; 532 | FField* DefaultObject; 533 | }; 534 | 535 | class FField 536 | { 537 | public: 538 | FPointer VTableObject; 539 | FFieldClass* ClassPrivate; 540 | FFieldVariant Owner; 541 | FField* Next; 542 | FName NamePrivate; 543 | // EObjectFlags FlagsPrivate; 544 | 545 | std::string GetName() 546 | { 547 | return NamePrivate.ToString(); 548 | } 549 | 550 | std::string GetTypeName() const 551 | { 552 | return ClassPrivate->Name.ToString(); 553 | } 554 | 555 | std::string GetFullName() 556 | { 557 | std::string temp; 558 | 559 | for (auto outer = Next; outer; outer = outer->Next) 560 | { 561 | temp = outer->GetName() + "." + temp; 562 | } 563 | 564 | temp = GetTypeName() + " " + temp + this->GetName(); 565 | return temp; 566 | } 567 | }; 568 | 569 | enum EPropertyType : uint8_t 570 | { 571 | ByteProperty, 572 | BoolProperty, 573 | IntProperty, 574 | FloatProperty, 575 | ObjectProperty, 576 | NameProperty, 577 | DelegateProperty, 578 | DoubleProperty, 579 | ArrayProperty, 580 | StructProperty, 581 | StrProperty, 582 | TextProperty, 583 | InterfaceProperty, 584 | MulticastDelegateProperty, 585 | WeakObjectProperty, 586 | LazyObjectProperty, 587 | AssetObjectProperty, 588 | SoftObjectProperty, 589 | UInt64Property, 590 | UInt32Property, 591 | UInt16Property, 592 | Int64Property, 593 | Int16Property, 594 | Int8Property, 595 | MapProperty, 596 | SetProperty, 597 | EnumProperty, 598 | FieldPathProperty, 599 | EnumAsByteProperty, 600 | 601 | Unknown = 0xFF 602 | }; 603 | 604 | class FProperty : public FField 605 | { 606 | public: 607 | int32_t ArrayDim; 608 | int32_t ElementSize; 609 | EPropertyFlags PropertyFlags; 610 | uint16_t RepIndex; 611 | TEnumAsByte BlueprintReplicationCondition; 612 | int32_t Offset_Internal; 613 | FName RepNotifyFunc; 614 | FProperty* PropertyLinkNext; 615 | FProperty* NextRef; 616 | FProperty* DestructorLinkNext; 617 | FProperty* PostConstructLinkNext; 618 | 619 | EPropertyType GetPropertyType(); 620 | }; 621 | 622 | class FBoolProperty : public FProperty 623 | { 624 | public: 625 | uint8_t FieldSize; 626 | uint8_t ByteOffset; 627 | uint8_t ByteMask; 628 | uint8_t FieldMask; 629 | 630 | FORCEINLINE bool IsNativeBool() const 631 | { 632 | return FieldMask == 0xff; 633 | } 634 | 635 | bool IsBitfield() const { return !IsNativeBool(); } 636 | 637 | static int GetBitPosition(uint8_t value) 638 | { 639 | int i4 = !(value & 0xf) << 2; 640 | value >>= i4; 641 | 642 | int i2 = !(value & 0x3) << 1; 643 | value >>= i2; 644 | 645 | int i1 = !(value & 0x1); 646 | 647 | int i0 = (value >> i1) & 1 ? 0 : -8; 648 | 649 | return i4 + i2 + i1 + i0; 650 | } 651 | 652 | std::pair GetMissingBitsCount(FBoolProperty* other) const 653 | { 654 | if (other == nullptr) 655 | { 656 | return { GetBitPosition(ByteMask), -1 }; 657 | } 658 | 659 | if (Offset_Internal == other->Offset_Internal) 660 | { 661 | return { GetBitPosition(ByteMask) - GetBitPosition(other->ByteMask) - 1, -1 }; 662 | } 663 | 664 | return { std::numeric_limits::digits - GetBitPosition(other->ByteMask) - 1, GetBitPosition(ByteMask) }; 665 | } 666 | }; 667 | 668 | class FObjectPropertyBase : public FProperty 669 | { 670 | public: 671 | UClass* PropertyClass; 672 | }; 673 | 674 | class FArrayProperty : public FProperty 675 | { 676 | public: 677 | EArrayPropertyFlags ArrayFlags; 678 | FProperty* Inner; 679 | }; 680 | 681 | class FStructProperty : public FProperty 682 | { 683 | public: 684 | class UStruct* Struct; 685 | }; 686 | 687 | class UField : public UObject 688 | { 689 | public: 690 | UField* Next; 691 | 692 | static class UClass* StaticClass(); 693 | }; 694 | 695 | class UEnum : public UObject 696 | { 697 | public: 698 | enum class ECppForm 699 | { 700 | Regular, 701 | Namespaced, 702 | EnumClass 703 | }; 704 | 705 | void* Pad; 706 | FString CppType; 707 | TArray> Names; 708 | ECppForm CppForm; 709 | EEnumFlags EnumFlags; 710 | 711 | static class UClass* StaticClass(); 712 | 713 | auto GetCPPString() 714 | { 715 | return CppType.ToString(); 716 | } 717 | 718 | auto GetEnumType() 719 | { 720 | int64_t maxValue = 0; 721 | 722 | for (int i = 0; i < Names.Num(); i++) 723 | if (Names[i].Value > maxValue) 724 | maxValue = Names[i].Value; 725 | 726 | if (maxValue <= 0x100) 727 | { 728 | return "uint8_t"; 729 | } 730 | else if (maxValue <= 0xFFFF) 731 | { 732 | return "uint16_t"; 733 | } 734 | else if (maxValue <= 0xFFFFFFFF) 735 | { 736 | return "uint32_t"; 737 | } 738 | else if (maxValue <= 0xFFFFFFFFFFFFFFFF) 739 | { 740 | return "uint64_t"; 741 | } 742 | } 743 | }; 744 | 745 | class FEnumProperty : public FProperty 746 | { 747 | public: 748 | FProperty* UnderlyingProp; 749 | UEnum* Enum; 750 | }; 751 | 752 | class FByteProperty : public FProperty 753 | { 754 | public: 755 | UEnum* Enum; 756 | }; 757 | 758 | class FInterfaceProperty : public FProperty 759 | { 760 | public: 761 | UClass* InterfaceClass; 762 | }; 763 | 764 | class FMapProperty : public FProperty 765 | { 766 | public: 767 | FProperty* KeyProp; 768 | FProperty* ValueProp; 769 | }; 770 | 771 | class FSetProperty : public FProperty 772 | { 773 | public: 774 | FProperty* ElementProp; 775 | }; 776 | 777 | class FSoftClassProperty : public FProperty 778 | { 779 | public: 780 | UClass* MetaClass; 781 | }; 782 | 783 | class FStructBaseChain 784 | { 785 | FStructBaseChain** StructBaseChainArray; 786 | int32_t NumStructBasesInChainMinusOne; 787 | }; 788 | 789 | class UStruct : public UField, FStructBaseChain 790 | { 791 | public: 792 | UStruct* SuperStruct; 793 | UField* Children; 794 | FField* ChildProperties; 795 | int32_t PropertiesSize; 796 | int32_t MinAlignment; 797 | TArray Script; 798 | FProperty* PropertyLink; 799 | FProperty* RefLink; 800 | FProperty* DestructorLink; 801 | FProperty* PostConstructLink; 802 | TArray ScriptAndPropertyObjectReferences; 803 | void* UnresolvedScriptProperties; 804 | void* UnversionedSchema; 805 | bool bHasAssetRegistrySearchableProperties; 806 | 807 | static class UClass* StaticClass(); 808 | }; 809 | 810 | class UFunction : public UStruct 811 | { 812 | public: 813 | EFunctionFlags FunctionFlags; 814 | uint8_t NumParms; 815 | uint16_t ParmsSize; 816 | uint16_t ReturnValueOffset; /** Memory offset of return value property */ 817 | uint16_t RPCId; /** Id of this RPC function call (must be FUNC_Net & (FUNC_NetService|FUNC_NetResponse)) */ 818 | uint16_t RPCResponseId; /** Id of the corresponding response call (must be FUNC_Net & FUNC_NetService) */ 819 | FProperty* FirstPropertyToInit; 820 | UFunction* EventGraphFunction; 821 | int32_t EventGraphCallOffset; 822 | void* Func; 823 | 824 | static class UClass* StaticClass(); 825 | }; 826 | 827 | struct FNativeFunctionLookup 828 | { 829 | FName Name; 830 | void* Pointer; 831 | }; 832 | 833 | class UClass : public UStruct 834 | { 835 | public: 836 | void* ClassConstructor; 837 | void* ClassVTableHelperCtorCaller; 838 | void* ClassAddReferencedObjects; 839 | mutable uint32_t ClassUnique : 31; 840 | uint32_t bCooked : 1; 841 | EClassFlags ClassFlags; 842 | EClassCastFlags ClassCastFlags; 843 | UClass* ClassWithin; 844 | UObject* ClassGeneratedBy; 845 | FName ClassConfigName; 846 | TArray ClassReps; 847 | TArray NetFields; 848 | int32_t FirstOwnedClassRep = 0; 849 | UObject* ClassDefaultObject; 850 | void* SparseClassData; 851 | void* SparseClassDataStruct; 852 | char FuncMap[0x50]; 853 | char SuperFuncMap[0x50]; 854 | void* SuperFuncMapLock; 855 | TArray Interfaces; 856 | TArray ReferenceTokenStream; 857 | // TArray TokenDebugInfo; 858 | char ReferenceTokenStreamCritical[0x28]; 859 | TArray NativeFunctionLookupTable; 860 | 861 | static class UClass* StaticClass(); 862 | }; 863 | 864 | class UBlueprintGeneratedClass : UClass 865 | { 866 | public: 867 | static class UClass* StaticClass(); 868 | }; 869 | 870 | class UAnimBlueprintGeneratedClass : UClass 871 | { 872 | public: 873 | static class UClass* StaticClass(); 874 | }; 875 | 876 | class UScriptStruct : UStruct 877 | { 878 | public: 879 | EStructFlags StructFlags; 880 | bool bPrepareCppStructOpsCompleted; 881 | void* CppStructOps; 882 | 883 | static class UClass* StaticClass(); 884 | }; 885 | 886 | struct FAssetData 887 | { 888 | struct FName ObjectPath; 889 | struct FName PackageName; 890 | struct FName PackagePath; 891 | struct FName AssetName; 892 | struct FName AssetClass; 893 | unsigned char padding_28[0x38]; 894 | }; -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------