mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-19 07:42:54 +00:00
Import code from previous AssetBuilder version
This commit is contained in:
parent
5609557516
commit
0d8432d4f7
7
.gitignore
vendored
7
.gitignore
vendored
@ -11,8 +11,13 @@
|
||||
*.obj
|
||||
*.log
|
||||
*.bak
|
||||
|
||||
ipch/*
|
||||
|
||||
.vs/
|
||||
local/
|
||||
bin/
|
||||
lib/
|
||||
local/
|
||||
obj/
|
||||
packages/
|
||||
TestResults/
|
@ -4,6 +4,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
VisualStudioVersion = 15.0.28307.852
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Linker", "src\Linker\Linker.vcxproj", "{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D} = {C3308B0A-D7C7-4560-B5F7-3654DD4B668D}
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7} = {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{EB945BC9-2451-4AB5-B434-BD07FAA2D06A}"
|
||||
EndProject
|
||||
@ -14,31 +18,177 @@ EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoneCommon", "src\ZoneCommon\ZoneCommon.vcxproj", "{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoneLoader", "src\ZoneLoader\ZoneLoader.vcxproj", "{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{FC57DC08-3496-4DCF-B52F-6EDC568B333C} = {FC57DC08-3496-4DCF-B52F-6EDC568B333C}
|
||||
{757FB12A-B410-4B76-B525-2D11A14DAD9D} = {757FB12A-B410-4B76-B525-2D11A14DAD9D}
|
||||
{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3} = {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7} = {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}
|
||||
{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681} = {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoneWriter", "src\ZoneWriter\ZoneWriter.vcxproj", "{B92A6638-68F9-45D2-AB03-6ED69E349381}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3} = {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7} = {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZoneCodeGenerator", "src\ZoneCodeGenerator\ZoneCodeGenerator.csproj", "{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{4D65E9A0-1798-4E93-A12F-128FFDC6A690}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZoneCodeGeneratorTests", "test\ZoneCodeGeneratorTests\ZoneCodeGeneratorTests.csproj", "{C29242DB-84D0-4A37-AD3F-19B72B23C7E0}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Crypto", "src\Crypto\Crypto.vcxproj", "{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{6A26AA97-96CF-4E2E-8883-47F0960F0E01} = {6A26AA97-96CF-4E2E-8883-47F0960F0E01}
|
||||
{599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77} = {599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}
|
||||
{CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7} = {CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Utils", "src\Utils\Utils.vcxproj", "{757FB12A-B410-4B76-B525-2D11A14DAD9D}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsquish", "thirdparty\libsquish\libsquish.vcxproj", "{E4E28AD7-6C59-419B-9463-817AF6384AC5}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtomcrypt", "thirdparty\libtomcrypt\libtomcrypt.vcxproj", "{CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtommath", "thirdparty\libtommath\libtommath.vcxproj", "{6A26AA97-96CF-4E2E-8883-47F0960F0E01}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minilzo", "thirdparty\minilzo\minilzo.vcxproj", "{4A4B90B9-1D76-4006-A1D7-D502DDD2C052}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "thirdparty\minizip\minizip.vcxproj", "{46297F21-4D05-4582-85EB-FD07B3243194}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "salsa20", "thirdparty\salsa20\salsa20.vcxproj", "{599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "thirdparty\zlib\zlib.vcxproj", "{FC57DC08-3496-4DCF-B52F-6EDC568B333C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Debug|x64.Build.0 = Debug|x64
|
||||
{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Debug|x86.Build.0 = Debug|Win32
|
||||
{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Release|x86.ActiveCfg = Release|Win32
|
||||
{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Release|x64.ActiveCfg = Release|x64
|
||||
{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Release|x64.Build.0 = Release|x64
|
||||
{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Release|x86.ActiveCfg = Debug|Win32
|
||||
{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Release|x86.Build.0 = Release|Win32
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Debug|x64.Build.0 = Debug|x64
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Debug|x86.Build.0 = Debug|Win32
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Release|x86.ActiveCfg = Release|Win32
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Release|x64.ActiveCfg = Release|x64
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Release|x64.Build.0 = Release|x64
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Release|x86.ActiveCfg = Debug|Win32
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Release|x86.Build.0 = Release|Win32
|
||||
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Debug|x64.Build.0 = Debug|x64
|
||||
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Debug|x86.Build.0 = Debug|Win32
|
||||
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Release|x86.ActiveCfg = Release|Win32
|
||||
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Release|x64.ActiveCfg = Release|x64
|
||||
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Release|x64.Build.0 = Release|x64
|
||||
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Release|x86.ActiveCfg = Debug|Win32
|
||||
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Release|x86.Build.0 = Release|Win32
|
||||
{B92A6638-68F9-45D2-AB03-6ED69E349381}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B92A6638-68F9-45D2-AB03-6ED69E349381}.Debug|x64.Build.0 = Debug|x64
|
||||
{B92A6638-68F9-45D2-AB03-6ED69E349381}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{B92A6638-68F9-45D2-AB03-6ED69E349381}.Debug|x86.Build.0 = Debug|Win32
|
||||
{B92A6638-68F9-45D2-AB03-6ED69E349381}.Release|x86.ActiveCfg = Release|Win32
|
||||
{B92A6638-68F9-45D2-AB03-6ED69E349381}.Release|x64.ActiveCfg = Release|x64
|
||||
{B92A6638-68F9-45D2-AB03-6ED69E349381}.Release|x64.Build.0 = Release|x64
|
||||
{B92A6638-68F9-45D2-AB03-6ED69E349381}.Release|x86.ActiveCfg = Debug|Win32
|
||||
{B92A6638-68F9-45D2-AB03-6ED69E349381}.Release|x86.Build.0 = Release|Win32
|
||||
{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Release|x86.ActiveCfg = Debug|Any CPU
|
||||
{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Release|x86.Build.0 = Debug|Any CPU
|
||||
{C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Release|x86.ActiveCfg = Debug|Any CPU
|
||||
{C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Release|x86.Build.0 = Debug|Any CPU
|
||||
{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Debug|x64.Build.0 = Debug|x64
|
||||
{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Debug|x86.Build.0 = Debug|Win32
|
||||
{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Release|x64.ActiveCfg = Release|x64
|
||||
{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Release|x64.Build.0 = Release|x64
|
||||
{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Release|x86.ActiveCfg = Release|Win32
|
||||
{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Release|x86.Build.0 = Release|Win32
|
||||
{757FB12A-B410-4B76-B525-2D11A14DAD9D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{757FB12A-B410-4B76-B525-2D11A14DAD9D}.Debug|x64.Build.0 = Debug|x64
|
||||
{757FB12A-B410-4B76-B525-2D11A14DAD9D}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{757FB12A-B410-4B76-B525-2D11A14DAD9D}.Debug|x86.Build.0 = Debug|Win32
|
||||
{757FB12A-B410-4B76-B525-2D11A14DAD9D}.Release|x64.ActiveCfg = Release|x64
|
||||
{757FB12A-B410-4B76-B525-2D11A14DAD9D}.Release|x64.Build.0 = Release|x64
|
||||
{757FB12A-B410-4B76-B525-2D11A14DAD9D}.Release|x86.ActiveCfg = Release|Win32
|
||||
{757FB12A-B410-4B76-B525-2D11A14DAD9D}.Release|x86.Build.0 = Release|Win32
|
||||
{E4E28AD7-6C59-419B-9463-817AF6384AC5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E4E28AD7-6C59-419B-9463-817AF6384AC5}.Debug|x64.Build.0 = Debug|x64
|
||||
{E4E28AD7-6C59-419B-9463-817AF6384AC5}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{E4E28AD7-6C59-419B-9463-817AF6384AC5}.Debug|x86.Build.0 = Debug|Win32
|
||||
{E4E28AD7-6C59-419B-9463-817AF6384AC5}.Release|x64.ActiveCfg = Release|x64
|
||||
{E4E28AD7-6C59-419B-9463-817AF6384AC5}.Release|x64.Build.0 = Release|x64
|
||||
{E4E28AD7-6C59-419B-9463-817AF6384AC5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E4E28AD7-6C59-419B-9463-817AF6384AC5}.Release|x86.Build.0 = Release|Win32
|
||||
{CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Debug|x64.Build.0 = Debug|x64
|
||||
{CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Debug|x86.Build.0 = Debug|Win32
|
||||
{CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Release|x64.ActiveCfg = Release|x64
|
||||
{CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Release|x64.Build.0 = Release|x64
|
||||
{CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Release|x86.ActiveCfg = Release|Win32
|
||||
{CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Release|x86.Build.0 = Release|Win32
|
||||
{6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Debug|x64.Build.0 = Debug|x64
|
||||
{6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Release|x64.ActiveCfg = Release|x64
|
||||
{6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Release|x64.Build.0 = Release|x64
|
||||
{6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Release|x86.Build.0 = Release|Win32
|
||||
{4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Debug|x64.Build.0 = Debug|x64
|
||||
{4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Debug|x86.Build.0 = Debug|Win32
|
||||
{4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Release|x64.ActiveCfg = Release|x64
|
||||
{4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Release|x64.Build.0 = Release|x64
|
||||
{4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Release|x86.ActiveCfg = Release|Win32
|
||||
{4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Release|x86.Build.0 = Release|Win32
|
||||
{46297F21-4D05-4582-85EB-FD07B3243194}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{46297F21-4D05-4582-85EB-FD07B3243194}.Debug|x64.Build.0 = Debug|x64
|
||||
{46297F21-4D05-4582-85EB-FD07B3243194}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{46297F21-4D05-4582-85EB-FD07B3243194}.Debug|x86.Build.0 = Debug|Win32
|
||||
{46297F21-4D05-4582-85EB-FD07B3243194}.Release|x64.ActiveCfg = Release|x64
|
||||
{46297F21-4D05-4582-85EB-FD07B3243194}.Release|x64.Build.0 = Release|x64
|
||||
{46297F21-4D05-4582-85EB-FD07B3243194}.Release|x86.ActiveCfg = Release|Win32
|
||||
{46297F21-4D05-4582-85EB-FD07B3243194}.Release|x86.Build.0 = Release|Win32
|
||||
{599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Debug|x64.Build.0 = Debug|x64
|
||||
{599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Debug|x86.Build.0 = Debug|Win32
|
||||
{599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Release|x64.ActiveCfg = Release|x64
|
||||
{599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Release|x64.Build.0 = Release|x64
|
||||
{599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Release|x86.ActiveCfg = Release|Win32
|
||||
{599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Release|x86.Build.0 = Release|Win32
|
||||
{FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Debug|x64.Build.0 = Debug|x64
|
||||
{FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Release|x64.ActiveCfg = Release|x64
|
||||
{FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Release|x64.Build.0 = Release|x64
|
||||
{FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -48,6 +198,17 @@ Global
|
||||
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7} = {6C048B51-3E90-45B8-8376-F3FFB5E216FC}
|
||||
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D} = {6C048B51-3E90-45B8-8376-F3FFB5E216FC}
|
||||
{B92A6638-68F9-45D2-AB03-6ED69E349381} = {6C048B51-3E90-45B8-8376-F3FFB5E216FC}
|
||||
{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3} = {6C048B51-3E90-45B8-8376-F3FFB5E216FC}
|
||||
{C29242DB-84D0-4A37-AD3F-19B72B23C7E0} = {4D65E9A0-1798-4E93-A12F-128FFDC6A690}
|
||||
{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681} = {6C048B51-3E90-45B8-8376-F3FFB5E216FC}
|
||||
{757FB12A-B410-4B76-B525-2D11A14DAD9D} = {6C048B51-3E90-45B8-8376-F3FFB5E216FC}
|
||||
{E4E28AD7-6C59-419B-9463-817AF6384AC5} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
|
||||
{CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
|
||||
{6A26AA97-96CF-4E2E-8883-47F0960F0E01} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
|
||||
{4A4B90B9-1D76-4006-A1D7-D502DDD2C052} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
|
||||
{46297F21-4D05-4582-85EB-FD07B3243194} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
|
||||
{599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
|
||||
{FC57DC08-3496-4DCF-B52F-6EDC568B333C} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {FBB5097F-0C5C-439C-8E82-19EF614DE3BE}
|
||||
|
19
src/Crypto/Crypto.cpp
Normal file
19
src/Crypto/Crypto.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "Crypto.h"
|
||||
#include "Impl/AlgorithmRSA.h"
|
||||
#include "Impl/AlgorithmSHA1.h"
|
||||
#include "Impl/AlgorithmSalsa20.h"
|
||||
|
||||
IHashFunction* Crypto::CreateSHA1()
|
||||
{
|
||||
return new AlgorithmSHA1();
|
||||
}
|
||||
|
||||
IStreamCipher* Crypto::CreateSalsa20(const uint8_t* keyBytes, const size_t keySize)
|
||||
{
|
||||
return new AlgorithmSalsa20(keyBytes, keySize);
|
||||
}
|
||||
|
||||
IPublicKeyAlgorithm* Crypto::CreateRSA(const IPublicKeyAlgorithm::HashingAlgorithm hashingAlgorithm, const RSAPaddingMode paddingMode)
|
||||
{
|
||||
return new AlgorithmRSA(hashingAlgorithm, paddingMode);
|
||||
}
|
20
src/Crypto/Crypto.h
Normal file
20
src/Crypto/Crypto.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "IHashFunction.h"
|
||||
#include "IStreamCipher.h"
|
||||
#include "IPublicKeyAlgorithm.h"
|
||||
|
||||
class Crypto
|
||||
{
|
||||
public:
|
||||
enum RSAPaddingMode
|
||||
{
|
||||
RSA_PADDING_PKS1,
|
||||
RSA_PADDING_PSS,
|
||||
};
|
||||
|
||||
static IHashFunction* CreateSHA1();
|
||||
|
||||
static IStreamCipher* CreateSalsa20(const uint8_t* keyBytes, size_t keySize);
|
||||
|
||||
static IPublicKeyAlgorithm* CreateRSA(IPublicKeyAlgorithm::HashingAlgorithm hashingAlgorithm, RSAPaddingMode paddingMode);
|
||||
};
|
204
src/Crypto/Crypto.vcxproj
Normal file
204
src/Crypto/Crypto.vcxproj
Normal file
@ -0,0 +1,204 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto.h" />
|
||||
<ClInclude Include="IHashFunction.h" />
|
||||
<ClInclude Include="Impl\AlgorithmRSA.h" />
|
||||
<ClInclude Include="Impl\AlgorithmSalsa20.h" />
|
||||
<ClInclude Include="Impl\AlgorithmSHA1.h" />
|
||||
<ClInclude Include="Impl\CryptoLibrary.h" />
|
||||
<ClInclude Include="IPublicKeyAlgorithm.h" />
|
||||
<ClInclude Include="IStreamCipher.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Crypto.cpp" />
|
||||
<ClCompile Include="Impl\AlgorithmRSA.cpp" />
|
||||
<ClCompile Include="Impl\AlgorithmSalsa20.cpp" />
|
||||
<ClCompile Include="Impl\AlgorithmSHA1.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>Crypto</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\</IntDir>
|
||||
<OutDir>$(SolutionDir)lib\$(Configuration)_$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\</IntDir>
|
||||
<OutDir>$(SolutionDir)lib\$(Configuration)_$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\</IntDir>
|
||||
<OutDir>$(SolutionDir)lib\$(Configuration)_$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\</IntDir>
|
||||
<OutDir>$(SolutionDir)lib\$(Configuration)_$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)thirdparty\libtomcrypt\headers;$(SolutionDir)thirdparty\salsa20;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<TreatSpecificWarningsAsErrors>4715;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
|
||||
<DisableSpecificWarnings>4221;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>libtomcrypt.lib;libtommath.lib;salsa20.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)lib\$(Configuration)_$(Platform)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4221</AdditionalOptions>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)thirdparty\libtomcrypt\headers;$(SolutionDir)thirdparty\salsa20;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<TreatSpecificWarningsAsErrors>4715;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
|
||||
<DisableSpecificWarnings>4221;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>libtomcrypt.lib;libtommath.lib;salsa20.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)lib\$(Configuration)_$(Platform)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4221</AdditionalOptions>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)thirdparty\libtomcrypt\headers;$(SolutionDir)thirdparty\salsa20;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<TreatSpecificWarningsAsErrors>4715;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
|
||||
<DisableSpecificWarnings>4221;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>libtomcrypt.lib;libtommath.lib;salsa20.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)lib\$(Configuration)_$(Platform)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4221</AdditionalOptions>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)thirdparty\libtomcrypt\headers;$(SolutionDir)thirdparty\salsa20;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<TreatSpecificWarningsAsErrors>4715;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
|
||||
<DisableSpecificWarnings>4221;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>libtomcrypt.lib;libtommath.lib;salsa20.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)lib\$(Configuration)_$(Platform)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4221</AdditionalOptions>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
12
src/Crypto/IHashFunction.h
Normal file
12
src/Crypto/IHashFunction.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
class IHashFunction
|
||||
{
|
||||
public:
|
||||
virtual ~IHashFunction() = default;
|
||||
|
||||
virtual size_t GetHashSize() = 0;
|
||||
virtual void Init() = 0;
|
||||
virtual void Process(const void* input, size_t inputSize) = 0;
|
||||
virtual void Finish(void* hashBuffer) = 0;
|
||||
};
|
21
src/Crypto/IPublicKeyAlgorithm.h
Normal file
21
src/Crypto/IPublicKeyAlgorithm.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class IPublicKeyAlgorithm
|
||||
{
|
||||
public:
|
||||
enum HashingAlgorithm
|
||||
{
|
||||
RSA_HASH_SHA256,
|
||||
RSA_HASH_SHA512
|
||||
};
|
||||
|
||||
virtual ~IPublicKeyAlgorithm() = default;
|
||||
|
||||
virtual bool SetKey(const uint8_t* keyData, size_t keySize) = 0;
|
||||
|
||||
// If needed add a signing method
|
||||
|
||||
virtual bool Verify(const uint8_t* signedData, size_t signedDataSize, const uint8_t* signature, size_t signatureSize) = 0;
|
||||
};
|
12
src/Crypto/IStreamCipher.h
Normal file
12
src/Crypto/IStreamCipher.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
class IStreamCipher
|
||||
{
|
||||
public:
|
||||
virtual ~IStreamCipher() = default;
|
||||
|
||||
virtual void SetIV(const uint8_t* iv, size_t ivSize) = 0;
|
||||
|
||||
virtual void Process(const void* plainText, void* cipherText, size_t amount) = 0;
|
||||
};
|
118
src/Crypto/Impl/AlgorithmRSA.cpp
Normal file
118
src/Crypto/Impl/AlgorithmRSA.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
#include "AlgorithmRSA.h"
|
||||
#include <cstring>
|
||||
|
||||
#include "CryptoLibrary.h"
|
||||
|
||||
class AlgorithmRSA::AlgorithmRSAImpl
|
||||
{
|
||||
rsa_key m_key{};
|
||||
HashingAlgorithm m_hash;
|
||||
Crypto::RSAPaddingMode m_padding;
|
||||
|
||||
const ltc_hash_descriptor* GetHashDescriptor() const
|
||||
{
|
||||
switch(m_hash)
|
||||
{
|
||||
case RSA_HASH_SHA256:
|
||||
return &sha256_desc;
|
||||
|
||||
default:
|
||||
case RSA_HASH_SHA512:
|
||||
return &sha512_desc;
|
||||
}
|
||||
}
|
||||
|
||||
int GetPaddingMode() const
|
||||
{
|
||||
switch(m_padding)
|
||||
{
|
||||
case Crypto::RSA_PADDING_PKS1:
|
||||
return LTC_PKCS_1_V1_5;
|
||||
|
||||
default:
|
||||
case Crypto::RSA_PADDING_PSS:
|
||||
return LTC_PKCS_1_PSS;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
AlgorithmRSAImpl(const HashingAlgorithm hash, const Crypto::RSAPaddingMode padding)
|
||||
{
|
||||
m_hash = hash;
|
||||
m_padding = padding;
|
||||
|
||||
CryptoLibrary::Init();
|
||||
}
|
||||
|
||||
~AlgorithmRSAImpl() = default;
|
||||
|
||||
AlgorithmRSAImpl(AlgorithmRSAImpl& other) = default;
|
||||
AlgorithmRSAImpl(AlgorithmRSAImpl&& other) = delete;
|
||||
|
||||
AlgorithmRSAImpl& operator=(AlgorithmRSAImpl const& other) = default;
|
||||
AlgorithmRSAImpl& operator=(AlgorithmRSAImpl&& other) = delete;
|
||||
|
||||
bool SetKey(const uint8_t* keyData, const size_t keySize)
|
||||
{
|
||||
return rsa_import(keyData, keySize, &m_key) == CRYPT_OK;
|
||||
}
|
||||
|
||||
bool Verify(const uint8_t* signedData, const size_t signedDataSize, const uint8_t* signature, const size_t signatureSize)
|
||||
{
|
||||
const ltc_hash_descriptor* hashDesc = GetHashDescriptor();
|
||||
const int hashId = register_hash(hashDesc);
|
||||
const int padding = GetPaddingMode();
|
||||
|
||||
int result;
|
||||
rsa_verify_hash_ex(signature, signatureSize, signedData, signedDataSize, padding, hashId, 8, &result, &m_key);
|
||||
|
||||
return result == 1;
|
||||
}
|
||||
};
|
||||
|
||||
AlgorithmRSA::AlgorithmRSA(const HashingAlgorithm hash, const Crypto::RSAPaddingMode padding)
|
||||
{
|
||||
m_impl = new AlgorithmRSAImpl(hash, padding);
|
||||
}
|
||||
|
||||
AlgorithmRSA::~AlgorithmRSA()
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
|
||||
AlgorithmRSA::AlgorithmRSA(AlgorithmRSA& other)
|
||||
{
|
||||
m_impl = new AlgorithmRSAImpl(*other.m_impl);
|
||||
}
|
||||
|
||||
AlgorithmRSA::AlgorithmRSA(AlgorithmRSA&& other) noexcept
|
||||
{
|
||||
m_impl = other.m_impl;
|
||||
other.m_impl = nullptr;
|
||||
}
|
||||
|
||||
AlgorithmRSA& AlgorithmRSA::operator=(AlgorithmRSA const& other)
|
||||
{
|
||||
m_impl = new AlgorithmRSAImpl(*other.m_impl);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
AlgorithmRSA& AlgorithmRSA::operator=(AlgorithmRSA&& other) noexcept
|
||||
{
|
||||
m_impl = other.m_impl;
|
||||
other.m_impl = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool AlgorithmRSA::SetKey(const uint8_t* keyData, size_t keySize)
|
||||
{
|
||||
return m_impl->SetKey(keyData, keySize);
|
||||
}
|
||||
|
||||
bool AlgorithmRSA::Verify(const uint8_t* signedData, const size_t signedDataSize, const uint8_t* signature, const size_t signatureSize)
|
||||
{
|
||||
return m_impl->Verify(signedData, signedDataSize, signature, signatureSize);
|
||||
}
|
24
src/Crypto/Impl/AlgorithmRSA.h
Normal file
24
src/Crypto/Impl/AlgorithmRSA.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "IPublicKeyAlgorithm.h"
|
||||
#include "Crypto.h"
|
||||
#include <cstdint>
|
||||
|
||||
class AlgorithmRSA final : public IPublicKeyAlgorithm
|
||||
{
|
||||
class AlgorithmRSAImpl;
|
||||
AlgorithmRSAImpl* m_impl;
|
||||
|
||||
public:
|
||||
AlgorithmRSA(HashingAlgorithm hash, Crypto::RSAPaddingMode padding);
|
||||
~AlgorithmRSA() override;
|
||||
|
||||
AlgorithmRSA(AlgorithmRSA& other);
|
||||
AlgorithmRSA(AlgorithmRSA&& other) noexcept;
|
||||
|
||||
AlgorithmRSA& operator=(AlgorithmRSA const& other);
|
||||
AlgorithmRSA& operator=(AlgorithmRSA&& other) noexcept;
|
||||
|
||||
bool SetKey(const uint8_t* keyData, size_t keySize) override;
|
||||
|
||||
bool Verify(const uint8_t* signedData, size_t signedDataSize, const uint8_t* signature, size_t signatureSize) override;
|
||||
};
|
63
src/Crypto/Impl/AlgorithmSHA1.cpp
Normal file
63
src/Crypto/Impl/AlgorithmSHA1.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "AlgorithmSHA1.h"
|
||||
|
||||
#include "CryptoLibrary.h"
|
||||
#include <cstdint>
|
||||
|
||||
class AlgorithmSHA1::AlgorithmSHA1Impl
|
||||
{
|
||||
hash_state m_state{};
|
||||
|
||||
public:
|
||||
AlgorithmSHA1Impl()
|
||||
{
|
||||
CryptoLibrary::Init();
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
sha1_init(&m_state);
|
||||
}
|
||||
|
||||
void Process(const void* input, const size_t inputSize)
|
||||
{
|
||||
sha1_process(&m_state, static_cast<const uint8_t*>(input), inputSize);
|
||||
}
|
||||
|
||||
void Finish(void* hashBuffer)
|
||||
{
|
||||
sha1_done(&m_state, static_cast<uint8_t*>(hashBuffer));
|
||||
}
|
||||
};
|
||||
|
||||
AlgorithmSHA1::AlgorithmSHA1()
|
||||
{
|
||||
m_impl = new AlgorithmSHA1Impl();
|
||||
}
|
||||
|
||||
AlgorithmSHA1::~AlgorithmSHA1()
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
|
||||
size_t AlgorithmSHA1::GetHashSize()
|
||||
{
|
||||
return HASH_SIZE;
|
||||
}
|
||||
|
||||
void AlgorithmSHA1::Init()
|
||||
{
|
||||
m_impl->Init();
|
||||
}
|
||||
|
||||
void AlgorithmSHA1::Process(const void* input, const size_t inputSize)
|
||||
{
|
||||
m_impl->Process(input, inputSize);
|
||||
}
|
||||
|
||||
void AlgorithmSHA1::Finish(void* hashBuffer)
|
||||
{
|
||||
m_impl->Finish(hashBuffer);
|
||||
}
|
20
src/Crypto/Impl/AlgorithmSHA1.h
Normal file
20
src/Crypto/Impl/AlgorithmSHA1.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "IHashFunction.h"
|
||||
|
||||
class AlgorithmSHA1 : public IHashFunction
|
||||
{
|
||||
class AlgorithmSHA1Impl;
|
||||
AlgorithmSHA1Impl* m_impl;
|
||||
|
||||
public:
|
||||
static const int HASH_SIZE = 20;
|
||||
|
||||
AlgorithmSHA1();
|
||||
~AlgorithmSHA1() override;
|
||||
|
||||
size_t GetHashSize() override;
|
||||
|
||||
void Init() override;
|
||||
void Process(const void* input, size_t inputSize) override;
|
||||
void Finish(void* hashBuffer) override;
|
||||
};
|
87
src/Crypto/Impl/AlgorithmSalsa20.cpp
Normal file
87
src/Crypto/Impl/AlgorithmSalsa20.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#include "AlgorithmSalsa20.h"
|
||||
#include "salsa20.h"
|
||||
#include <cassert>
|
||||
#include <exception>
|
||||
|
||||
class AlgorithmSalsa20::AlgorithmSalsa20Impl
|
||||
{
|
||||
salsa20_ctx m_context{};
|
||||
|
||||
public:
|
||||
AlgorithmSalsa20Impl(const uint8_t* keyBytes, const size_t keySize)
|
||||
{
|
||||
Salsa20_KeySetup(&m_context, keyBytes, keySize * 8);
|
||||
}
|
||||
|
||||
~AlgorithmSalsa20Impl() = default;
|
||||
|
||||
AlgorithmSalsa20Impl(AlgorithmSalsa20Impl& other) = default;
|
||||
AlgorithmSalsa20Impl(AlgorithmSalsa20Impl&& other) = delete;
|
||||
|
||||
AlgorithmSalsa20Impl& operator=(AlgorithmSalsa20Impl const& other) = default;
|
||||
AlgorithmSalsa20Impl& operator=(AlgorithmSalsa20Impl&& other) = delete;
|
||||
|
||||
void SetIV(const uint8_t* iv, const size_t ivSize)
|
||||
{
|
||||
assert(ivSize == 8);
|
||||
|
||||
if(ivSize != 8)
|
||||
{
|
||||
throw std::exception("Salsa20 IV size must be 8");
|
||||
}
|
||||
|
||||
Salsa20_IVSetup(&m_context, iv);
|
||||
}
|
||||
|
||||
void Process(const void* plainText, void* cipherText, const size_t amount)
|
||||
{
|
||||
Salsa20_Encrypt_Bytes(&m_context, static_cast<const uint8_t*>(plainText), static_cast<uint8_t*>(cipherText), amount);
|
||||
}
|
||||
};
|
||||
|
||||
AlgorithmSalsa20::AlgorithmSalsa20(const uint8_t* keyBytes, const size_t keySize)
|
||||
{
|
||||
m_impl = new AlgorithmSalsa20Impl(keyBytes, keySize);
|
||||
}
|
||||
|
||||
AlgorithmSalsa20::~AlgorithmSalsa20()
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
|
||||
AlgorithmSalsa20::AlgorithmSalsa20(AlgorithmSalsa20& other)
|
||||
{
|
||||
m_impl = new AlgorithmSalsa20Impl(*other.m_impl);
|
||||
}
|
||||
|
||||
AlgorithmSalsa20::AlgorithmSalsa20(AlgorithmSalsa20&& other) noexcept
|
||||
{
|
||||
m_impl = other.m_impl;
|
||||
other.m_impl = nullptr;
|
||||
}
|
||||
|
||||
AlgorithmSalsa20& AlgorithmSalsa20::operator=(AlgorithmSalsa20 const& other)
|
||||
{
|
||||
m_impl = new AlgorithmSalsa20Impl(*other.m_impl);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
AlgorithmSalsa20& AlgorithmSalsa20::operator=(AlgorithmSalsa20&& other) noexcept
|
||||
{
|
||||
m_impl = other.m_impl;
|
||||
other.m_impl = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void AlgorithmSalsa20::SetIV(const uint8_t* iv, const size_t ivSize)
|
||||
{
|
||||
m_impl->SetIV(iv, ivSize);
|
||||
}
|
||||
|
||||
void AlgorithmSalsa20::Process(const void* plainText, void* cipherText, const size_t amount)
|
||||
{
|
||||
m_impl->Process(plainText, cipherText, amount);
|
||||
}
|
21
src/Crypto/Impl/AlgorithmSalsa20.h
Normal file
21
src/Crypto/Impl/AlgorithmSalsa20.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "IStreamCipher.h"
|
||||
|
||||
class AlgorithmSalsa20 final : public IStreamCipher
|
||||
{
|
||||
class AlgorithmSalsa20Impl;
|
||||
AlgorithmSalsa20Impl* m_impl;
|
||||
|
||||
public:
|
||||
AlgorithmSalsa20(const uint8_t* keyBytes, size_t keySize);
|
||||
~AlgorithmSalsa20() override;
|
||||
|
||||
AlgorithmSalsa20(AlgorithmSalsa20& other);
|
||||
AlgorithmSalsa20(AlgorithmSalsa20&& other) noexcept;
|
||||
|
||||
AlgorithmSalsa20& operator=(AlgorithmSalsa20 const& other);
|
||||
AlgorithmSalsa20& operator=(AlgorithmSalsa20&& other) noexcept;
|
||||
|
||||
void SetIV(const uint8_t* iv, size_t ivSize) override;
|
||||
void Process(const void* plainText, void* cipherText, size_t amount) override;
|
||||
};
|
20
src/Crypto/Impl/CryptoLibrary.h
Normal file
20
src/Crypto/Impl/CryptoLibrary.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#include "tomcrypt.h"
|
||||
|
||||
class CryptoLibrary
|
||||
{
|
||||
public:
|
||||
static void Init()
|
||||
{
|
||||
static bool initialized = false;
|
||||
|
||||
if(!initialized)
|
||||
{
|
||||
initialized = true;
|
||||
|
||||
ltc_mp = ltm_desc;
|
||||
}
|
||||
}
|
||||
};
|
@ -91,11 +91,13 @@
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<TreatSpecificWarningsAsErrors>4715;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(TargetDir)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4221</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
@ -109,6 +111,7 @@
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<TreatSpecificWarningsAsErrors>4715;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -116,17 +119,26 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(TargetDir)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4221</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>$(TargetDir)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4221</AdditionalOptions>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<TreatSpecificWarningsAsErrors>4715;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>$(TargetDir)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4221</AdditionalOptions>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<TreatSpecificWarningsAsErrors>4715;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
179
src/Utils/Utils.vcxproj
Normal file
179
src/Utils/Utils.vcxproj
Normal file
@ -0,0 +1,179 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Utils\ClassUtils.h" />
|
||||
<ClInclude Include="Utils\FileAPI.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Utils\FileAPI.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{757FB12A-B410-4B76-B525-2D11A14DAD9D}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>Utils</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)lib\$(Configuration)_$(Platform)\</OutDir>
|
||||
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)lib\$(Configuration)_$(Platform)\</OutDir>
|
||||
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)lib\$(Configuration)_$(Platform)\</OutDir>
|
||||
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)lib\$(Configuration)_$(Platform)\</OutDir>
|
||||
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<TreatSpecificWarningsAsErrors>4715;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalOptions>/ignore:4221</AdditionalOptions>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<TreatSpecificWarningsAsErrors>4715;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalOptions>/ignore:4221</AdditionalOptions>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<TreatSpecificWarningsAsErrors>4715;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalOptions>/ignore:4221</AdditionalOptions>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<TreatSpecificWarningsAsErrors>4715;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalOptions>/ignore:4221</AdditionalOptions>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
3
src/Utils/Utils/ClassUtils.h
Normal file
3
src/Utils/Utils/ClassUtils.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define STR(x) #x
|
145
src/Utils/Utils/FileAPI.cpp
Normal file
145
src/Utils/Utils/FileAPI.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
#include "FileAPI.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
bool FileAPI::FileExists(const std::string& fileName)
|
||||
{
|
||||
struct stat st{};
|
||||
|
||||
return stat(fileName.c_str(), &st) >= 0 && !(st.st_mode & S_IFDIR);
|
||||
}
|
||||
|
||||
uint64_t FileAPI::FileSize(const std::string& fileName)
|
||||
{
|
||||
struct stat st{};
|
||||
|
||||
if (stat(fileName.c_str(), &st) >= 0 && !(st.st_mode & S_IFDIR))
|
||||
{
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FileAPI::DirectoryExists(const std::string& directoryName)
|
||||
{
|
||||
struct stat st{};
|
||||
|
||||
return stat(directoryName.c_str(), &st) >= 0 && st.st_mode & S_IFDIR;
|
||||
}
|
||||
|
||||
FileAPI::File FileAPI::Open(const std::string& filename, const Mode mode)
|
||||
{
|
||||
const char* modeStr;
|
||||
switch(mode)
|
||||
{
|
||||
default:
|
||||
case MODE_READ:
|
||||
modeStr = "rb";
|
||||
break;
|
||||
|
||||
case MODE_WRITE:
|
||||
modeStr = "wb";
|
||||
break;
|
||||
}
|
||||
|
||||
FILE* handle;
|
||||
if (fopen_s(&handle, filename.c_str(), modeStr) != 0)
|
||||
{
|
||||
return File(nullptr);
|
||||
}
|
||||
|
||||
return File(handle);
|
||||
}
|
||||
|
||||
FileAPI::File::File()
|
||||
{
|
||||
this->m_handle = nullptr;
|
||||
}
|
||||
|
||||
FileAPI::File::File(void* handle)
|
||||
{
|
||||
this->m_handle = handle;
|
||||
}
|
||||
|
||||
FileAPI::File::File(File&& f) noexcept
|
||||
{
|
||||
m_handle = f.m_handle;
|
||||
f.m_handle = nullptr;
|
||||
}
|
||||
|
||||
FileAPI::File::~File()
|
||||
{
|
||||
this->Close();
|
||||
}
|
||||
|
||||
FileAPI::File& FileAPI::File::operator=(File&& f) noexcept
|
||||
{
|
||||
m_handle = f.m_handle;
|
||||
f.m_handle = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool FileAPI::File::IsOpen() const
|
||||
{
|
||||
return this->m_handle != nullptr;
|
||||
}
|
||||
|
||||
size_t FileAPI::File::Read(void* buffer, const size_t elementSize, const size_t elementCount) const
|
||||
{
|
||||
if (!this->IsOpen())
|
||||
return 0;
|
||||
|
||||
return fread(buffer, elementSize, elementCount, static_cast<FILE*>(m_handle));
|
||||
}
|
||||
|
||||
size_t FileAPI::File::Write(void* data, const size_t elementSize, const size_t elementCount) const
|
||||
{
|
||||
if (!this->IsOpen())
|
||||
return 0;
|
||||
|
||||
return fwrite(data, elementSize, elementCount, static_cast<FILE*>(m_handle));
|
||||
}
|
||||
|
||||
void FileAPI::File::Skip(const size_t amount) const
|
||||
{
|
||||
if(!this->IsOpen())
|
||||
return;
|
||||
|
||||
fseek(static_cast<FILE*>(m_handle), amount, SEEK_CUR);
|
||||
}
|
||||
|
||||
size_t FileAPI::File::Printf(char* fmt, ...) const
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (!this->IsOpen())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
const int result = fprintf(static_cast<FILE*>(m_handle), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t FileAPI::File::Pos() const
|
||||
{
|
||||
return _ftelli64(static_cast<FILE*>(m_handle));
|
||||
}
|
||||
|
||||
void FileAPI::File::Goto(const int64_t pos) const
|
||||
{
|
||||
_fseeki64(static_cast<FILE*>(m_handle), pos, SEEK_SET);
|
||||
}
|
||||
|
||||
void FileAPI::File::Close()
|
||||
{
|
||||
if (this->m_handle != nullptr)
|
||||
{
|
||||
fclose(static_cast<FILE*>(m_handle));
|
||||
this->m_handle = nullptr;
|
||||
}
|
||||
}
|
43
src/Utils/Utils/FileAPI.h
Normal file
43
src/Utils/Utils/FileAPI.h
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class FileAPI
|
||||
{
|
||||
public:
|
||||
enum Mode
|
||||
{
|
||||
MODE_READ = 0,
|
||||
MODE_WRITE = 1
|
||||
};
|
||||
|
||||
class File
|
||||
{
|
||||
void* m_handle;
|
||||
|
||||
public:
|
||||
File();
|
||||
explicit File(void* handle);
|
||||
File(File&) = delete;
|
||||
File(File&& f) noexcept;
|
||||
~File();
|
||||
|
||||
File& operator=(File&) = delete;
|
||||
File& operator=(File&& f) noexcept;
|
||||
|
||||
bool IsOpen() const;
|
||||
size_t Read(void* buffer, size_t elementSize, size_t elementCount) const;
|
||||
size_t Write(void* data, size_t elementSize, size_t elementCount) const;
|
||||
void Skip(size_t amount) const;
|
||||
size_t Printf(char* fmt, ...) const;
|
||||
int64_t Pos() const;
|
||||
void Goto(int64_t pos) const;
|
||||
void Close();
|
||||
};
|
||||
|
||||
static bool FileExists(const std::string& fileName);
|
||||
static uint64_t FileSize(const std::string& fileName);
|
||||
static bool DirectoryExists(const std::string& directoryName);
|
||||
static File Open(const std::string& filename, Mode mode);
|
||||
};
|
6
src/ZoneCodeGenerator/App.config
Normal file
6
src/ZoneCodeGenerator/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
||||
</startup>
|
||||
</configuration>
|
9
src/ZoneCodeGenerator/Domain/DataException.cs
Normal file
9
src/ZoneCodeGenerator/Domain/DataException.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class DataException : LoadingException
|
||||
{
|
||||
public DataException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
20
src/ZoneCodeGenerator/Domain/DataType.cs
Normal file
20
src/ZoneCodeGenerator/Domain/DataType.cs
Normal file
@ -0,0 +1,20 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
abstract class DataType
|
||||
{
|
||||
public string Namespace { get; }
|
||||
public string Name { get; }
|
||||
public DataTypeType Type { get; }
|
||||
public string FullName => string.IsNullOrEmpty(Namespace) ? Name : $"{Namespace}::{Name}";
|
||||
|
||||
public abstract int Alignment { get; }
|
||||
public abstract int Size { get; }
|
||||
|
||||
protected DataType(string _namespace, string name, DataTypeType type)
|
||||
{
|
||||
Namespace = _namespace;
|
||||
Name = name;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
}
|
47
src/ZoneCodeGenerator/Domain/DataTypeBaseType.cs
Normal file
47
src/ZoneCodeGenerator/Domain/DataTypeBaseType.cs
Normal file
@ -0,0 +1,47 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class DataTypeBaseType : DataType
|
||||
{
|
||||
public static readonly DataTypeBaseType FLOAT = new DataTypeBaseType("float", 4);
|
||||
public static readonly DataTypeBaseType DOUBLE = new DataTypeBaseType("double", 8);
|
||||
public static readonly DataTypeBaseType BOOL = new DataTypeBaseType("bool", 1);
|
||||
public static readonly DataTypeBaseType CHAR = new DataTypeBaseType("char", 1);
|
||||
public static readonly DataTypeBaseType CONST_CHAR = new DataTypeBaseType("const char", 1);
|
||||
public static readonly DataTypeBaseType UNSIGNED_CHAR = new DataTypeBaseType("unsigned char", 1);
|
||||
public static readonly DataTypeBaseType SHORT = new DataTypeBaseType("short", 2);
|
||||
public static readonly DataTypeBaseType UNSIGNED_SHORT = new DataTypeBaseType("unsigned short", 2);
|
||||
public static readonly DataTypeBaseType INT = new DataTypeBaseType("int", 4);
|
||||
public static readonly DataTypeBaseType UNSIGNED_INT = new DataTypeBaseType("unsigned int", 4);
|
||||
public static readonly DataTypeBaseType LONG = new DataTypeBaseType("long", 4);
|
||||
public static readonly DataTypeBaseType UNSIGNED_LONG = new DataTypeBaseType("unsigned long", 4);
|
||||
public static readonly DataTypeBaseType LONG_LONG = new DataTypeBaseType("long long", 8);
|
||||
public static readonly DataTypeBaseType UNSIGNED_LONG_LONG = new DataTypeBaseType("unsigned long long", 8);
|
||||
public static readonly DataTypeBaseType VOID = new DataTypeBaseType("void", 0);
|
||||
|
||||
public static readonly DataTypeBaseType[] BASE_TYPES = {
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
BOOL,
|
||||
CHAR,
|
||||
CONST_CHAR,
|
||||
UNSIGNED_CHAR,
|
||||
SHORT,
|
||||
UNSIGNED_SHORT,
|
||||
INT,
|
||||
UNSIGNED_INT,
|
||||
LONG,
|
||||
UNSIGNED_LONG,
|
||||
LONG_LONG,
|
||||
UNSIGNED_LONG_LONG,
|
||||
VOID
|
||||
};
|
||||
|
||||
public override int Size { get; }
|
||||
public override int Alignment => Size;
|
||||
|
||||
private DataTypeBaseType(string name, int size) : base("", name, DataTypeType.BaseType)
|
||||
{
|
||||
Size = size;
|
||||
}
|
||||
}
|
||||
}
|
19
src/ZoneCodeGenerator/Domain/DataTypeEnum.cs
Normal file
19
src/ZoneCodeGenerator/Domain/DataTypeEnum.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class DataTypeEnum : DataType
|
||||
{
|
||||
public DataTypeBaseType ParentType { get; }
|
||||
public List<EnumMember> Members { get; }
|
||||
|
||||
public override int Size => ParentType.Size;
|
||||
public override int Alignment => ParentType.Alignment;
|
||||
|
||||
public DataTypeEnum(string _namespace, string name, DataTypeBaseType parentType) : base(_namespace, name, DataTypeType.Enum)
|
||||
{
|
||||
Members = new List<EnumMember>();
|
||||
ParentType = parentType;
|
||||
}
|
||||
}
|
||||
}
|
46
src/ZoneCodeGenerator/Domain/DataTypeStruct.cs
Normal file
46
src/ZoneCodeGenerator/Domain/DataTypeStruct.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using ZoneCodeGenerator.Utils;
|
||||
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class DataTypeStruct : DataTypeWithMembers
|
||||
{
|
||||
public DataTypeStruct(string _namespace, string name, int pack) : base(_namespace, name, pack, DataTypeType.Struct)
|
||||
{
|
||||
}
|
||||
|
||||
protected override int CalculateSize()
|
||||
{
|
||||
var currentSize = 0;
|
||||
var currentBitOffset = 0;
|
||||
|
||||
foreach (var member in Members)
|
||||
{
|
||||
if (member.VariableType.HasCustomBitSize)
|
||||
{
|
||||
currentBitOffset += member.VariableType.CustomBitSize.GetValueOrDefault(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentBitOffset > 0)
|
||||
{
|
||||
currentBitOffset = currentBitOffset.Align(8);
|
||||
currentSize += currentBitOffset / 8;
|
||||
currentBitOffset = 0;
|
||||
}
|
||||
|
||||
currentSize = currentSize.Align(Math.Min(member.Alignment, Pack));
|
||||
currentSize += member.VariableType.Size;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentBitOffset > 0)
|
||||
{
|
||||
currentBitOffset = currentBitOffset.Align(8);
|
||||
currentSize += currentBitOffset / 8;
|
||||
}
|
||||
|
||||
return currentSize.Align(Alignment);
|
||||
}
|
||||
}
|
||||
}
|
11
src/ZoneCodeGenerator/Domain/DataTypeType.cs
Normal file
11
src/ZoneCodeGenerator/Domain/DataTypeType.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
enum DataTypeType
|
||||
{
|
||||
Struct,
|
||||
Union,
|
||||
Enum,
|
||||
Typedef,
|
||||
BaseType
|
||||
}
|
||||
}
|
15
src/ZoneCodeGenerator/Domain/DataTypeTypedef.cs
Normal file
15
src/ZoneCodeGenerator/Domain/DataTypeTypedef.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class DataTypeTypedef : DataType
|
||||
{
|
||||
public TypeDeclaration TypeDefinition { get; }
|
||||
|
||||
public DataTypeTypedef(string _namespace, string name, TypeDeclaration typeDefinitionDeclaration) : base(_namespace, name, DataTypeType.Typedef)
|
||||
{
|
||||
TypeDefinition = typeDefinitionDeclaration;
|
||||
}
|
||||
|
||||
public override int Alignment => TypeDefinition.Alignment;
|
||||
public override int Size => TypeDefinition.Size;
|
||||
}
|
||||
}
|
20
src/ZoneCodeGenerator/Domain/DataTypeUnion.cs
Normal file
20
src/ZoneCodeGenerator/Domain/DataTypeUnion.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.Linq;
|
||||
using ZoneCodeGenerator.Utils;
|
||||
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class DataTypeUnion : DataTypeWithMembers
|
||||
{
|
||||
public DataTypeUnion(string _namespace, string name, int pack) : base(_namespace, name, pack, DataTypeType.Union)
|
||||
{
|
||||
}
|
||||
|
||||
protected override int CalculateSize()
|
||||
{
|
||||
return Members
|
||||
.Select(variable => variable.VariableType.Size)
|
||||
.Max()
|
||||
.Align(Alignment);
|
||||
}
|
||||
}
|
||||
}
|
50
src/ZoneCodeGenerator/Domain/DataTypeWithMembers.cs
Normal file
50
src/ZoneCodeGenerator/Domain/DataTypeWithMembers.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
abstract class DataTypeWithMembers : DataType
|
||||
{
|
||||
public int? AlignmentOverride { get; set; }
|
||||
private int alignment;
|
||||
public override int Alignment => AlignmentOverride ?? alignment;
|
||||
|
||||
private int size;
|
||||
public override int Size => size;
|
||||
|
||||
public int Pack { get; }
|
||||
|
||||
public List<Variable> Members { get; }
|
||||
|
||||
private bool finalized;
|
||||
public void FinalizeDataType()
|
||||
{
|
||||
if (finalized) return;
|
||||
|
||||
finalized = true;
|
||||
CalculateProperties();
|
||||
}
|
||||
|
||||
protected DataTypeWithMembers(string _namespace, string name, int pack, DataTypeType type) : base(_namespace, name, type)
|
||||
{
|
||||
Members = new List<Variable>();
|
||||
Pack = pack;
|
||||
finalized = false;
|
||||
}
|
||||
|
||||
private void CalculateProperties()
|
||||
{
|
||||
foreach (var member in Members
|
||||
.Select(variable => variable.VariableType.Type)
|
||||
.OfType<DataTypeWithMembers>())
|
||||
{
|
||||
member.FinalizeDataType();
|
||||
}
|
||||
|
||||
alignment = Members.Select(variable => variable.Alignment).Max();
|
||||
size = CalculateSize();
|
||||
}
|
||||
|
||||
protected abstract int CalculateSize();
|
||||
}
|
||||
}
|
14
src/ZoneCodeGenerator/Domain/EnumMember.cs
Normal file
14
src/ZoneCodeGenerator/Domain/EnumMember.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class EnumMember
|
||||
{
|
||||
public string Name { get; }
|
||||
public long Value { get; }
|
||||
|
||||
public EnumMember(string name, long value)
|
||||
{
|
||||
Name = name;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
namespace ZoneCodeGenerator.Domain.FastFileStructure
|
||||
{
|
||||
class FastFileBlock
|
||||
{
|
||||
public enum Type
|
||||
{
|
||||
Temp,
|
||||
Runtime,
|
||||
Delay,
|
||||
Normal
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public int Index { get; }
|
||||
public Type BlockType { get; }
|
||||
public bool IsDefault { get; }
|
||||
public bool IsTemp => BlockType == Type.Temp;
|
||||
public bool IsRuntime => BlockType == Type.Runtime;
|
||||
public bool IsDelay => BlockType == Type.Delay;
|
||||
public bool IsNormal => BlockType == Type.Normal;
|
||||
|
||||
public FastFileBlock(string name, int index, Type blockType, bool isDefault)
|
||||
{
|
||||
Name = name;
|
||||
Index = index;
|
||||
BlockType = blockType;
|
||||
IsDefault = isDefault;
|
||||
}
|
||||
}
|
||||
}
|
47
src/ZoneCodeGenerator/Domain/ForwardDeclaration.cs
Normal file
47
src/ZoneCodeGenerator/Domain/ForwardDeclaration.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class ForwardDeclaration : DataType
|
||||
{
|
||||
private DataType forwardedType;
|
||||
|
||||
public DataType ForwardedType
|
||||
{
|
||||
get => forwardedType;
|
||||
|
||||
set
|
||||
{
|
||||
if (forwardedType == null)
|
||||
{
|
||||
if(value.Type != Type)
|
||||
throw new DataException($"Type of forwarded type '{Name}' does not match previous declaration");
|
||||
|
||||
forwardedType = value;
|
||||
}
|
||||
else if(forwardedType != value)
|
||||
{
|
||||
throw new DataException($"Tried to set forwarded type '{Name}' multiple times with different types");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ForwardDeclaration(string _namespace, string name, DataTypeType dataTypeType) : base(_namespace, name, dataTypeType)
|
||||
{
|
||||
switch (dataTypeType)
|
||||
{
|
||||
case DataTypeType.Enum:
|
||||
case DataTypeType.Struct:
|
||||
case DataTypeType.Union:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Cannot create forward declaration for type '{dataTypeType}'");
|
||||
}
|
||||
forwardedType = null;
|
||||
}
|
||||
|
||||
public override int Alignment => 0;
|
||||
public override int Size => 0;
|
||||
}
|
||||
}
|
59
src/ZoneCodeGenerator/Domain/Namespace.cs
Normal file
59
src/ZoneCodeGenerator/Domain/Namespace.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class Namespace
|
||||
{
|
||||
private static readonly Regex nameRegex = new Regex(@"^[a-zA-Z_$][a-zA-Z0-9_$]*$");
|
||||
private readonly Stack<string> namespaceStack;
|
||||
|
||||
public Namespace()
|
||||
{
|
||||
namespaceStack = new Stack<string>();
|
||||
}
|
||||
|
||||
public void Push(string _namespace)
|
||||
{
|
||||
if(!nameRegex.IsMatch(_namespace))
|
||||
throw new ArgumentException("Namespace name invalid");
|
||||
|
||||
namespaceStack.Push(_namespace);
|
||||
}
|
||||
|
||||
public string Pop()
|
||||
{
|
||||
return namespaceStack.Pop();
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
if (namespaceStack.Count == 0)
|
||||
return "";
|
||||
|
||||
var result = "";
|
||||
var stackSnapshot = namespaceStack.ToArray();
|
||||
|
||||
// The stack is read from top to bottom. Therefore we need to access it in reverse order here.
|
||||
for(var i = stackSnapshot.Length - 1; i >= 0; i--)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(result))
|
||||
result += "::";
|
||||
result += stackSnapshot[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return GetName();
|
||||
}
|
||||
|
||||
public static string Combine(Namespace _namespace, string typename)
|
||||
{
|
||||
return $"{_namespace}::{typename}";
|
||||
}
|
||||
}
|
||||
}
|
7
src/ZoneCodeGenerator/Domain/ReferenceType.cs
Normal file
7
src/ZoneCodeGenerator/Domain/ReferenceType.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
abstract class ReferenceType
|
||||
{
|
||||
|
||||
}
|
||||
}
|
12
src/ZoneCodeGenerator/Domain/ReferenceTypeArray.cs
Normal file
12
src/ZoneCodeGenerator/Domain/ReferenceTypeArray.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class ReferenceTypeArray : ReferenceType
|
||||
{
|
||||
public int ArraySize { get; }
|
||||
|
||||
public ReferenceTypeArray(int arraySize)
|
||||
{
|
||||
ArraySize = arraySize;
|
||||
}
|
||||
}
|
||||
}
|
6
src/ZoneCodeGenerator/Domain/ReferenceTypePointer.cs
Normal file
6
src/ZoneCodeGenerator/Domain/ReferenceTypePointer.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class ReferenceTypePointer : ReferenceType
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
namespace ZoneCodeGenerator.Domain.StructureInformation
|
||||
{
|
||||
class MemberInformation
|
||||
{
|
||||
public StructureInformation StructureType { get; }
|
||||
public Variable Member { get; set; }
|
||||
public bool IsScriptString { get; set; }
|
||||
|
||||
public MemberInformation(Variable member, StructureInformation structureType)
|
||||
{
|
||||
Member = member;
|
||||
StructureType = structureType;
|
||||
IsScriptString = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ZoneCodeGenerator.Domain.FastFileStructure;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Domain.StructureInformation
|
||||
{
|
||||
class StructureInformation
|
||||
{
|
||||
public DataTypeWithMembers Type { get; }
|
||||
public bool IsUnion => Type is DataTypeUnion;
|
||||
public FastFileBlock Block { get; set; }
|
||||
|
||||
public EnumMember AssetEnumEntry { get; set; }
|
||||
public bool IsAsset => AssetEnumEntry != null;
|
||||
|
||||
private int? fastFileAlign;
|
||||
public bool HasNonDefaultAlign => fastFileAlign != null;
|
||||
public int FastFileAlign
|
||||
{
|
||||
get => fastFileAlign ?? Type.Alignment;
|
||||
set => fastFileAlign = value;
|
||||
}
|
||||
|
||||
public List<StructureInformation> Usages { get; }
|
||||
public List<MemberInformation> OrderedMembers { get; }
|
||||
public bool NonEmbeddedReferenceExists { get; set; }
|
||||
public bool PointerReferenceExists { get; set; }
|
||||
public bool ArrayReferenceExists { get; set; }
|
||||
|
||||
public bool HasNameMember => Type.Members.Any(variable => variable.Name.Equals("name", StringComparison.CurrentCultureIgnoreCase));
|
||||
|
||||
public StructureInformation(DataTypeWithMembers type)
|
||||
{
|
||||
AssetEnumEntry = null;
|
||||
fastFileAlign = null;
|
||||
Type = type;
|
||||
NonEmbeddedReferenceExists = false;
|
||||
PointerReferenceExists = false;
|
||||
ArrayReferenceExists = false;
|
||||
Usages = new List<StructureInformation>();
|
||||
OrderedMembers = new List<MemberInformation>();
|
||||
}
|
||||
}
|
||||
}
|
70
src/ZoneCodeGenerator/Domain/TypeDeclaration.cs
Normal file
70
src/ZoneCodeGenerator/Domain/TypeDeclaration.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class TypeDeclaration
|
||||
{
|
||||
private const int PointerSize = 4;
|
||||
|
||||
private DataType type;
|
||||
public DataType Type
|
||||
{
|
||||
get
|
||||
{
|
||||
if (type is DataTypeTypedef typedef)
|
||||
{
|
||||
return typedef.TypeDefinition.Type;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
set => type = value;
|
||||
}
|
||||
|
||||
public int? CustomBitSize { get; }
|
||||
|
||||
public bool HasCustomBitSize => CustomBitSize != null;
|
||||
|
||||
private readonly List<ReferenceType> references;
|
||||
public IReadOnlyList<ReferenceType> References => references.AsReadOnly();
|
||||
|
||||
public int Alignment => references.OfType<ReferenceTypePointer>().Any() ? PointerSize : type.Alignment;
|
||||
|
||||
public int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
var currentSize = Type.Size;
|
||||
|
||||
foreach (var reference in References.Reverse())
|
||||
{
|
||||
switch (reference)
|
||||
{
|
||||
case ReferenceTypePointer _:
|
||||
currentSize = PointerSize;
|
||||
break;
|
||||
case ReferenceTypeArray array:
|
||||
currentSize *= array.ArraySize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return currentSize;
|
||||
}
|
||||
}
|
||||
|
||||
public TypeDeclaration(DataType type, List<ReferenceType> references)
|
||||
{
|
||||
this.type = type;
|
||||
this.references = references ?? new List<ReferenceType>();
|
||||
CustomBitSize = null;
|
||||
}
|
||||
|
||||
public TypeDeclaration(DataType type, int customBitSize, List<ReferenceType> references) : this(type, references)
|
||||
{
|
||||
CustomBitSize = customBitSize;
|
||||
}
|
||||
}
|
||||
}
|
19
src/ZoneCodeGenerator/Domain/Variable.cs
Normal file
19
src/ZoneCodeGenerator/Domain/Variable.cs
Normal file
@ -0,0 +1,19 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class Variable
|
||||
{
|
||||
public string Name { get; }
|
||||
|
||||
public int? AlignmentOverride { get; set; }
|
||||
|
||||
public int Alignment => AlignmentOverride ?? VariableType.Alignment;
|
||||
|
||||
public TypeDeclaration VariableType { get; }
|
||||
|
||||
public Variable(string name, TypeDeclaration type)
|
||||
{
|
||||
Name = name;
|
||||
VariableType = type;
|
||||
}
|
||||
}
|
||||
}
|
98
src/ZoneCodeGenerator/Generating/CodeGenerator.cs
Normal file
98
src/ZoneCodeGenerator/Generating/CodeGenerator.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using ZoneCodeGenerator.Domain.StructureInformation;
|
||||
using ZoneCodeGenerator.Interface;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Generating
|
||||
{
|
||||
static class CodeGenerator
|
||||
{
|
||||
private class GeneratorPreset
|
||||
{
|
||||
public string FileName { get; }
|
||||
public string TemplateName { get; }
|
||||
|
||||
public GeneratorPreset(string fileName, string templateName)
|
||||
{
|
||||
FileName = fileName;
|
||||
TemplateName = templateName;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, GeneratorPreset> presets =
|
||||
new Dictionary<string, GeneratorPreset>(StringComparer.CurrentCultureIgnoreCase)
|
||||
{
|
||||
{
|
||||
"ZoneLoad", new GeneratorPreset("$asset/$asset_load_db", "ZoneLoad.stg")
|
||||
},
|
||||
{
|
||||
"ZoneWrite", new GeneratorPreset("$asset/$asset_write_db", "ZoneWrite.stg")
|
||||
}
|
||||
};
|
||||
|
||||
public static IEnumerable<string> Presets => presets.Keys;
|
||||
|
||||
public static bool GenerateCodeForPreset(string presetName, StructureInformation asset, CUISession session)
|
||||
{
|
||||
if (!presets.ContainsKey(presetName))
|
||||
return false;
|
||||
|
||||
var preset = presets[presetName];
|
||||
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(session.GeneratorOutputPath))
|
||||
Directory.CreateDirectory(session.GeneratorOutputPath);
|
||||
|
||||
var codeTemplate = CodeTemplate.FromResources(preset.TemplateName);
|
||||
|
||||
if (codeTemplate == null)
|
||||
{
|
||||
Console.WriteLine($"Could not find template '{preset.TemplateName}'");
|
||||
return false;
|
||||
}
|
||||
|
||||
var resolvedFileName = preset.FileName.Replace("$asset", asset.Type.Name.ToLower());
|
||||
var fullPath = Path.Combine(session.GeneratorOutputPath, resolvedFileName);
|
||||
var folderOfFile = Path.GetDirectoryName(fullPath);
|
||||
|
||||
if (!Directory.Exists(folderOfFile))
|
||||
Directory.CreateDirectory(folderOfFile);
|
||||
|
||||
var renderingContext = RenderingContext.BuildContext(session, asset);
|
||||
|
||||
if (renderingContext == null)
|
||||
return false;
|
||||
|
||||
var generatedCode = false;
|
||||
if (codeTemplate.HasHeaderTemplate)
|
||||
{
|
||||
generatedCode = true;
|
||||
using (var fileStream = new FileStream(fullPath + ".h", FileMode.Create))
|
||||
{
|
||||
codeTemplate.RenderHeaderFile(fileStream, renderingContext);
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
if (codeTemplate.HasSourceTemplate)
|
||||
{
|
||||
generatedCode = true;
|
||||
using (var fileStream = new FileStream(fullPath + ".cpp", FileMode.Create))
|
||||
{
|
||||
codeTemplate.RenderSourceFile(fileStream, renderingContext);
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
return generatedCode;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
54
src/ZoneCodeGenerator/Generating/CodeTemplate.cs
Normal file
54
src/ZoneCodeGenerator/Generating/CodeTemplate.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System.IO;
|
||||
using Antlr4.StringTemplate;
|
||||
|
||||
namespace ZoneCodeGenerator.Generating
|
||||
{
|
||||
class CodeTemplate
|
||||
{
|
||||
private const string SourceTemplateName = "source";
|
||||
private const string HeaderTemplateName = "header";
|
||||
|
||||
private readonly TemplateGroup templateGroup;
|
||||
|
||||
public bool HasSourceTemplate => templateGroup.IsDefined(SourceTemplateName);
|
||||
public bool HasHeaderTemplate => templateGroup.IsDefined(HeaderTemplateName);
|
||||
|
||||
private CodeTemplate(TemplateGroup templateGroup)
|
||||
{
|
||||
this.templateGroup = templateGroup;
|
||||
templateGroup.RegisterRenderer(typeof(string), new StringRenderer());
|
||||
}
|
||||
|
||||
public static CodeTemplate FromResources(string fileName)
|
||||
{
|
||||
var templateGroup = new TemplateGroupResources(fileName);
|
||||
|
||||
templateGroup.Load();
|
||||
|
||||
return new CodeTemplate(templateGroup);
|
||||
}
|
||||
|
||||
public void RenderSourceFile(Stream stream, RenderingContext context)
|
||||
{
|
||||
RenderTemplate(stream, templateGroup.GetInstanceOf(SourceTemplateName), context);
|
||||
}
|
||||
|
||||
public void RenderHeaderFile(Stream stream, RenderingContext context)
|
||||
{
|
||||
RenderTemplate(stream, templateGroup.GetInstanceOf(HeaderTemplateName), context);
|
||||
}
|
||||
|
||||
private static void RenderTemplate(Stream stream, Template template, RenderingContext context)
|
||||
{
|
||||
if (template == null)
|
||||
return;
|
||||
|
||||
template.Add("context", context);
|
||||
|
||||
using (var writer = new StreamWriter(stream))
|
||||
{
|
||||
template.Write(new AutoIndentWriter(writer));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
58
src/ZoneCodeGenerator/Generating/RenderingContext.cs
Normal file
58
src/ZoneCodeGenerator/Generating/RenderingContext.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Domain.FastFileStructure;
|
||||
using ZoneCodeGenerator.Domain.StructureInformation;
|
||||
using ZoneCodeGenerator.Interface;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Generating
|
||||
{
|
||||
class RenderingContext
|
||||
{
|
||||
public string Game { get; set; }
|
||||
public StructureInformation Asset { get; set; }
|
||||
public HashSet<StructureInformation> Structures { get; }
|
||||
public IEnumerable<StructureInformation> ReferencedAssets => Structures.Where(inf => inf.IsAsset && inf != Asset);
|
||||
|
||||
public List<FastFileBlock> Blocks { get; private set; }
|
||||
|
||||
public FastFileBlock DefaultNormalBlock => Blocks.FirstOrDefault(block => block.IsDefault && block.IsNormal) ??
|
||||
Blocks.FirstOrDefault(block => block.IsNormal);
|
||||
|
||||
private RenderingContext()
|
||||
{
|
||||
Structures = new HashSet<StructureInformation>();
|
||||
}
|
||||
|
||||
private void AddToContext(StructureInformation structureInformation)
|
||||
{
|
||||
if (!Structures.Add(structureInformation))
|
||||
return;
|
||||
|
||||
if (structureInformation.IsAsset && structureInformation != Asset)
|
||||
return;
|
||||
|
||||
foreach (var member in structureInformation.OrderedMembers)
|
||||
{
|
||||
if(member.StructureType != null)
|
||||
AddToContext(member.StructureType);
|
||||
}
|
||||
}
|
||||
|
||||
public static RenderingContext BuildContext(CUISession session, StructureInformation asset)
|
||||
{
|
||||
var context = new RenderingContext
|
||||
{
|
||||
Asset = asset,
|
||||
Game = session.Game,
|
||||
Blocks = session.Repository.GetAllFastFileBlocks().ToList()
|
||||
};
|
||||
|
||||
context.AddToContext(asset);
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
}
|
126
src/ZoneCodeGenerator/Generating/TemplateGroupResources.cs
Normal file
126
src/ZoneCodeGenerator/Generating/TemplateGroupResources.cs
Normal file
@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Antlr.Runtime;
|
||||
using Antlr4.StringTemplate;
|
||||
using Antlr4.StringTemplate.Compiler;
|
||||
using Antlr4.StringTemplate.Misc;
|
||||
|
||||
namespace ZoneCodeGenerator.Generating
|
||||
{
|
||||
public class TemplateGroupResources : TemplateGroup
|
||||
{
|
||||
private const string ResourceBasePath = "ZoneCodeGenerator.Generating.Templates";
|
||||
private const char DefaultDelimiterStart = '<';
|
||||
private const char DefaultDelimiterStop = '>';
|
||||
|
||||
private bool alreadyLoaded;
|
||||
private readonly string fileName;
|
||||
|
||||
public TemplateGroupResources(string fileName, char delimiterStartChar, char delimiterStopChar) : base(delimiterStartChar, delimiterStopChar)
|
||||
{
|
||||
this.fileName = fileName;
|
||||
alreadyLoaded = false;
|
||||
}
|
||||
|
||||
public TemplateGroupResources(string fileName) : this(fileName, DefaultDelimiterStart, DefaultDelimiterStop)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void ImportTemplates(IToken fileNameToken)
|
||||
{
|
||||
var text = Utility.Strip(fileNameToken.Text, 1);
|
||||
|
||||
TemplateGroup importingGroup = null;
|
||||
if (text.EndsWith(GroupFileExtension))
|
||||
{
|
||||
importingGroup = new TemplateGroupResources(text, DelimiterStartChar, DelimiterStopChar);
|
||||
}
|
||||
else if (text.EndsWith(TemplateFileExtension))
|
||||
{
|
||||
importingGroup = new TemplateGroup(DelimiterStartChar, DelimiterStopChar);
|
||||
|
||||
using (var resourceStream = StreamFromResources(text))
|
||||
{
|
||||
if (resourceStream != null)
|
||||
{
|
||||
using (var textStream = new StreamReader(resourceStream))
|
||||
{
|
||||
var inputStream = new ANTLRReaderStream(textStream)
|
||||
{
|
||||
name = fileName
|
||||
};
|
||||
|
||||
importingGroup.LoadTemplateFile("/", fileName, inputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (importingGroup != null)
|
||||
{
|
||||
importingGroup.Load();
|
||||
ImportTemplates(importingGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorManager.CompiletimeError(ErrorType.CANT_IMPORT, null, fileNameToken, text);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
if (alreadyLoaded)
|
||||
return;
|
||||
alreadyLoaded = true;
|
||||
|
||||
if (Verbose)
|
||||
Console.WriteLine($"loading group file '{fileName}'");
|
||||
|
||||
using (var resourceStream = StreamFromResources(fileName))
|
||||
{
|
||||
if (resourceStream == null)
|
||||
{
|
||||
if (Verbose)
|
||||
Console.WriteLine($"Resource '{fileName}' doesn't exist");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
using (var textStream = new StreamReader(resourceStream))
|
||||
{
|
||||
var inputStream = new ANTLRReaderStream(textStream)
|
||||
{
|
||||
name = fileName
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var lexer = new GroupLexer(inputStream);
|
||||
var tokenStream = new CommonTokenStream(lexer);
|
||||
var parser = new GroupParser(tokenStream);
|
||||
|
||||
parser.group(this, "/");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ErrorManager.IOError(null, ErrorType.CANT_LOAD_GROUP_FILE, ex, FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Stream StreamFromResources(string fileName)
|
||||
{
|
||||
var resourceName = $"{ResourceBasePath}.{fileName}";
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
return assembly.GetManifestResourceStream(resourceName);
|
||||
}
|
||||
|
||||
public override string Name => "TemplateGroupResources";
|
||||
|
||||
public override string FileName => Name;
|
||||
}
|
||||
}
|
2
src/ZoneCodeGenerator/Generating/Templates/Common.stg
Normal file
2
src/ZoneCodeGenerator/Generating/Templates/Common.stg
Normal file
@ -0,0 +1,2 @@
|
||||
test() ::= <<
|
||||
>>
|
225
src/ZoneCodeGenerator/Generating/Templates/ZoneLoad.stg
Normal file
225
src/ZoneCodeGenerator/Generating/Templates/ZoneLoad.stg
Normal file
@ -0,0 +1,225 @@
|
||||
delimiters "$", "$"
|
||||
|
||||
import "Common.stg"
|
||||
|
||||
Capital(name) ::= "$name; format=\"cap\"$"
|
||||
|
||||
LoaderClassName(asset) ::= "Loader_$asset.Type.Name$"
|
||||
|
||||
HeaderConstructor(context) ::= "$LoaderClassName(context.Asset)$(IZoneScriptStringProvider* scriptStringProvider, Zone* zone, IZoneInputStream* stream);"
|
||||
|
||||
HeaderPtrLoadMethodDeclaration(structure) ::= "void LoadPtr_$structure.Type.Name$($structure.Type.FullName$** pPtr);"
|
||||
HeaderArrayLoadMethodDeclaration(structure) ::= "void LoadArray_$structure.Type.Name$($structure.Type.FullName$** pArray, size_t count, bool atStreamStart);"
|
||||
HeaderLoadMethodDeclaration(structure) ::= "void Load_$structure.Type.Name$($structure.Type.FullName$** p$structure.Type.Name$, bool atStreamStart);"
|
||||
|
||||
HeaderGetNameMethodDeclaration(asset) ::= "static std::string GetAssetName($asset.Type.FullName$* p$asset.Type.Name$);"
|
||||
HeaderAssetLoadMethodDeclaration(asset) ::= "void LoadAsset_$asset.Type.Name$($asset.Type.FullName$** pPtr);"
|
||||
|
||||
HeaderDeclaration(structure) ::= <%
|
||||
$if(structure.PointerReferenceExists)$
|
||||
$HeaderPtrLoadMethodDeclaration(structure)$
|
||||
$\n$
|
||||
$endif$
|
||||
|
||||
$if(structure.ArrayReferenceExists)$
|
||||
$HeaderArrayLoadMethodDeclaration(structure)$
|
||||
$\n$
|
||||
$endif$
|
||||
|
||||
$if(structure.NonEmbeddedReferenceExists)$
|
||||
$HeaderLoadMethodDeclaration(structure)$
|
||||
$\n$
|
||||
$endif$
|
||||
%>
|
||||
|
||||
// =======================
|
||||
// Header file entry point
|
||||
// =======================
|
||||
header(context) ::= <<
|
||||
// ====================================================================
|
||||
// This file has been generated by ZoneCodeGenerator.
|
||||
// Do not modify.
|
||||
// Any changes will be discarded when regenerating.
|
||||
// ====================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Loading/AssetLoader.h"
|
||||
#include "Game/$context.Game$/$context.Game$.h"
|
||||
#include <string>
|
||||
|
||||
namespace $context.Game$
|
||||
{
|
||||
class $LoaderClassName(context.Asset)$
|
||||
{
|
||||
$context.Structures:{structure | $if(!structure.IsAsset)$$HeaderDeclaration(structure)$$endif$}$
|
||||
$HeaderLoadMethodDeclaration(context.Asset)$
|
||||
$HeaderAssetLoadMethodDeclaration(context.Asset)$
|
||||
|
||||
public:
|
||||
$HeaderConstructor(context)$
|
||||
|
||||
$HeaderPtrLoadMethodDeclaration(context.Asset)$
|
||||
$HeaderGetNameMethodDeclaration(context.Asset)$
|
||||
};
|
||||
}
|
||||
>>
|
||||
|
||||
IncludeHeaderOfOtherAsset(asset) ::= <<
|
||||
#include "../$asset.Type.Name$/$asset.Type.Name; format="lower"$_load_db.h"
|
||||
|
||||
>>
|
||||
|
||||
LoadMethod(structure, context) ::= <<
|
||||
void $LoaderClassName(context.Asset)$::Load_$structure.Type.Name$($structure.Type.FullName$* p$structure.Type.Name$, const bool atStreamStart)
|
||||
{
|
||||
assert(p$structure.Type.Name$ != nullptr);
|
||||
|
||||
if(atStreamStart)
|
||||
m_stream->Load<$structure.Type.FullName$>();
|
||||
$if(structure.Block.IsTemp)$
|
||||
|
||||
m_stream->PushBlock($context.DefaultNormalBlock.Name$);
|
||||
$endif$
|
||||
|
||||
// Load content here
|
||||
$if(structure.Block.IsTemp)$
|
||||
|
||||
m_stream->PopBlock();
|
||||
$endif$
|
||||
}
|
||||
>>
|
||||
|
||||
LoadPtrMethod(structure, context) ::= <<
|
||||
void $LoaderClassName(context.Asset)$::LoadPtr_$structure.Type.Name$($structure.Type.FullName$** pPtr)
|
||||
{
|
||||
assert(pPtr != nullptr);
|
||||
|
||||
m_stream->PushBlock($structure.Block.Name$);
|
||||
|
||||
if(*pPtr != nullptr)
|
||||
{
|
||||
$if(structure.Block.IsTemp)$
|
||||
if(*pPtr == PTR_FOLLOWING || *pPtr == PTR_INSERT)
|
||||
$else$
|
||||
if(*pPtr == PTR_FOLLOWING)
|
||||
$endif$
|
||||
{
|
||||
$if(structure.Block.IsTemp)$
|
||||
$structure.Type.FullName$** toInsert = nullptr;
|
||||
if(*pPtr == PTR_INSERT)
|
||||
toInsert = m_stream->InsertPointer<$structure.Type.FullName$>();
|
||||
|
||||
$endif$
|
||||
$if(structure.HasNonDefaultAlign)$
|
||||
*pPtr = m_stream->Alloc<$structure.Type.FullName$>($structure.FastFileAlign$);
|
||||
$else$
|
||||
*pPtr = m_stream->Alloc<$structure.Type.FullName$>();
|
||||
$endif$
|
||||
Load_$structure.Type.Name$(*pPtr, true);
|
||||
$if(structure.IsAsset)$
|
||||
LoadAsset_$structure.Type.Name$(pPtr);
|
||||
$endif$
|
||||
$if(structure.Block.IsTemp)$
|
||||
|
||||
if(toInsert != nullptr)
|
||||
*toInsert = *pPtr;
|
||||
$endif$
|
||||
}
|
||||
else
|
||||
{
|
||||
$if(structure.Block.IsTemp)$
|
||||
*pPtr = m_stream->ConvertOffsetToAlias(*ptr);
|
||||
$else$
|
||||
*pPtr = m_stream->ConvertOffsetToPointer(*ptr);
|
||||
$endif$
|
||||
}
|
||||
}
|
||||
|
||||
m_stream->PopBlock();
|
||||
}
|
||||
>>
|
||||
|
||||
LoadArrayMethod(structure, context) ::= <<
|
||||
void $LoaderClassName(context.Asset)$::LoadArray_$structure.Type.Name$($structure.Type.FullName$** pArray, const size_t count, const bool atStreamStart)
|
||||
{
|
||||
assert(pArray != nullptr);
|
||||
|
||||
if(atStreamStart)
|
||||
m_stream->Load<$structure.Type.FullName$>(count);
|
||||
|
||||
for(size_t index = 0; index < count; index++)
|
||||
{
|
||||
Load_$structure.Type.Name$(&pArray[index], false);
|
||||
}
|
||||
}
|
||||
>>
|
||||
|
||||
SourceDefinition(structure, context) ::= <<
|
||||
$if(structure.NonEmbeddedReferenceExists)$
|
||||
$LoadMethod(structure, context)$
|
||||
|
||||
$endif$
|
||||
$if(structure.PointerReferenceExists)$
|
||||
$LoadPtrMethod(structure, context)$
|
||||
|
||||
$endif$
|
||||
$if(structure.ArrayReferenceExists)$
|
||||
$LoadArrayMethod(structure, context)$
|
||||
|
||||
$endif$
|
||||
>>
|
||||
|
||||
ConstructorMethod(context) ::= <<
|
||||
$LoaderClassName(context.Asset)$::$LoaderClassName(context.Asset)$(IZoneScriptStringProvider* scriptStringProvider, Zone* zone, IZoneInputStream* stream)
|
||||
: AssetLoader($context.Asset.AssetEnumEntry.Name$, scriptStringProvider, zone, stream){}
|
||||
>>
|
||||
|
||||
LoadAssetMethod(structure, context) ::= <<
|
||||
void $LoaderClassName(context.Asset)$::LoadAsset_$structure.Type.Name$($structure.Type.FullName$** pPtr)
|
||||
{
|
||||
assert(pPtr != nullptr);
|
||||
*pPtr = static_cast<$structure.Type.FullName$*>(LinkAsset(GetAssetName(*pPtr), *pPtr));
|
||||
}
|
||||
>>
|
||||
|
||||
GetNameMethod(context) ::= <<
|
||||
std::string $LoaderClassName(context.Asset)$::GetAssetName($context.Asset.Type.FullName$* p$context.Asset.Type.Name$)
|
||||
{
|
||||
$if(context.Asset.HasNameMember)$
|
||||
return p$context.Asset.Type.Name$->name;
|
||||
$else$
|
||||
return "$context.Asset.Type.Name$";
|
||||
$endif$
|
||||
}
|
||||
>>
|
||||
|
||||
// =======================
|
||||
// Source file entry point
|
||||
// =======================
|
||||
source(context) ::= <<
|
||||
// ====================================================================
|
||||
// This file has been generated by ZoneCodeGenerator.
|
||||
// Do not modify.
|
||||
// Any changes will be discarded when regenerating.
|
||||
// ====================================================================
|
||||
|
||||
#include "$context.Asset.Type.Name; format="lower"$_load_db.h"
|
||||
#include <cassert>
|
||||
|
||||
// Referenced Assets:
|
||||
$context.ReferencedAssets:IncludeHeaderOfOtherAsset()$
|
||||
|
||||
using namespace $context.Game$;
|
||||
|
||||
$ConstructorMethod(context)$
|
||||
|
||||
$context.Structures:{structure | $if(!structure.IsAsset)$$SourceDefinition(structure, context)$$endif$}$
|
||||
$LoadMethod(context.Asset, context)$
|
||||
|
||||
$LoadAssetMethod(context.Asset, context)$
|
||||
|
||||
$LoadPtrMethod(context.Asset, context)$
|
||||
|
||||
$GetNameMethod(context)$
|
||||
>>
|
38
src/ZoneCodeGenerator/Generating/Templates/ZoneWrite.stg
Normal file
38
src/ZoneCodeGenerator/Generating/Templates/ZoneWrite.stg
Normal file
@ -0,0 +1,38 @@
|
||||
delimiters "$", "$"
|
||||
|
||||
import "Common.stg"
|
||||
|
||||
WriterClassName(asset) ::= "$asset.Type.Name; format=\"cap\"$ZoneWriter"
|
||||
|
||||
// =======================
|
||||
// Header file entry point
|
||||
// =======================
|
||||
header(context) ::= <<
|
||||
#pragma once
|
||||
|
||||
namespace ZoneLoader
|
||||
{
|
||||
class $WriterClassName(context.Asset)$
|
||||
{
|
||||
public:
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
>>
|
||||
|
||||
IncludeHeaderOfOtherAsset(asset) ::= <<
|
||||
#include "../$asset.Type.Name$/$asset.Type.Name; format="lower"$_write_db.h"
|
||||
|
||||
>>
|
||||
|
||||
// =======================
|
||||
// Source file entry point
|
||||
// =======================
|
||||
source(context) ::= <<
|
||||
#include "$context.Asset.Type.Name; format="lower"$_write_db.h"
|
||||
|
||||
// Referenced Assets:
|
||||
$context.ReferencedAssets:IncludeHeaderOfOtherAsset()$
|
||||
|
||||
// TODO
|
||||
>>
|
113
src/ZoneCodeGenerator/Interface/Arguments/ArgumentParser.cs
Normal file
113
src/ZoneCodeGenerator/Interface/Arguments/ArgumentParser.cs
Normal file
@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ZoneCodeGenerator.Interface.Arguments
|
||||
{
|
||||
class ArgumentParser
|
||||
{
|
||||
private readonly CommandLineOption[] options;
|
||||
|
||||
private readonly List<string> noOptionArgs;
|
||||
private readonly Dictionary<CommandLineOption, List<string>> optionArgs;
|
||||
|
||||
public IReadOnlyList<string> Arguments => noOptionArgs.AsReadOnly();
|
||||
|
||||
public ArgumentParser(CommandLineOption[] options)
|
||||
{
|
||||
this.options = options;
|
||||
noOptionArgs = new List<string>();
|
||||
optionArgs = new Dictionary<CommandLineOption, List<string>>();
|
||||
}
|
||||
|
||||
public bool ParseArguments(string[] args)
|
||||
{
|
||||
noOptionArgs.Clear();
|
||||
optionArgs.Clear();
|
||||
|
||||
for (var i = 0; i < args.Length; i++)
|
||||
{
|
||||
var arg = args[i];
|
||||
|
||||
if (arg.StartsWith("-"))
|
||||
{
|
||||
CommandLineOption matchedOption;
|
||||
|
||||
if (arg.StartsWith("--"))
|
||||
{
|
||||
var longNameToFind = arg.Substring(2);
|
||||
matchedOption = options.FirstOrDefault(option => longNameToFind.Equals(option.LongName));
|
||||
}
|
||||
else
|
||||
{
|
||||
var shortNameToFind = arg.Substring(1);
|
||||
matchedOption = options.FirstOrDefault(option => shortNameToFind.Equals(option.ShortName));
|
||||
}
|
||||
|
||||
if (matchedOption == null)
|
||||
{
|
||||
Console.WriteLine($"Unknown option '{arg}'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
List<string> parameters;
|
||||
if (optionArgs.ContainsKey(matchedOption))
|
||||
{
|
||||
if (!matchedOption.MultiUse)
|
||||
{
|
||||
Console.WriteLine($"Option '{arg}' already specified.");
|
||||
return false;
|
||||
}
|
||||
|
||||
parameters = optionArgs[matchedOption];
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters = new List<string>();
|
||||
optionArgs.Add(matchedOption, parameters);
|
||||
}
|
||||
|
||||
if (i + matchedOption.ParameterCount >= args.Length)
|
||||
{
|
||||
Console.WriteLine($"Not enough parameters for option '{arg}'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var parameter = 0; parameter < matchedOption.ParameterCount; parameter++)
|
||||
{
|
||||
if (args[i + parameter + 1].StartsWith("-"))
|
||||
{
|
||||
Console.WriteLine($"Not enough parameters for option '{arg}'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
parameters.Add(args[i + parameter + 1]);
|
||||
}
|
||||
|
||||
i += matchedOption.ParameterCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
noOptionArgs.Add(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsOptionSpecified(CommandLineOption option)
|
||||
{
|
||||
return optionArgs.ContainsKey(option);
|
||||
}
|
||||
|
||||
public string GetValueForOption(CommandLineOption option)
|
||||
{
|
||||
return IsOptionSpecified(option) ? string.Join(" ", optionArgs[option]) : null;
|
||||
}
|
||||
|
||||
public IReadOnlyList<string> GetParametersForOption(CommandLineOption option)
|
||||
{
|
||||
return IsOptionSpecified(option) ? optionArgs[option].AsReadOnly() : null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ZoneCodeGenerator.Interface.Arguments
|
||||
{
|
||||
class CommandLineOption
|
||||
{
|
||||
public string ShortName { get; private set; }
|
||||
public string LongName { get; private set; }
|
||||
public string Description { get; private set; }
|
||||
public string Category { get; private set; }
|
||||
public bool MultiUse { get; private set; }
|
||||
|
||||
private readonly List<string> parameters;
|
||||
public IReadOnlyList<string> Parameters => parameters.AsReadOnly();
|
||||
public int ParameterCount => parameters.Count;
|
||||
|
||||
private CommandLineOption()
|
||||
{
|
||||
ShortName = null;
|
||||
LongName = null;
|
||||
Description = "";
|
||||
Category = "";
|
||||
MultiUse = false;
|
||||
parameters = new List<string>();
|
||||
}
|
||||
|
||||
public class CommandLineOptionBuilder
|
||||
{
|
||||
private readonly CommandLineOption option;
|
||||
|
||||
private CommandLineOptionBuilder()
|
||||
{
|
||||
option = new CommandLineOption();
|
||||
}
|
||||
|
||||
public static CommandLineOptionBuilder Create()
|
||||
{
|
||||
return new CommandLineOptionBuilder();
|
||||
}
|
||||
|
||||
public CommandLineOptionBuilder WithShortName(string shortName)
|
||||
{
|
||||
option.ShortName = shortName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandLineOptionBuilder WithLongName(string longName)
|
||||
{
|
||||
option.LongName = longName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandLineOptionBuilder WithDescription(string description)
|
||||
{
|
||||
option.Description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandLineOptionBuilder WithCategory(string category)
|
||||
{
|
||||
option.Category = category;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandLineOptionBuilder WithParameter(string argumentName)
|
||||
{
|
||||
option.parameters.Add(argumentName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandLineOptionBuilder Reusable()
|
||||
{
|
||||
option.MultiUse = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandLineOption Build()
|
||||
{
|
||||
return option;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
108
src/ZoneCodeGenerator/Interface/Arguments/UsageInformation.cs
Normal file
108
src/ZoneCodeGenerator/Interface/Arguments/UsageInformation.cs
Normal file
@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ZoneCodeGenerator.Interface.Arguments
|
||||
{
|
||||
static class UsageInformation
|
||||
{
|
||||
public static string FromCommandlineOptions(CommandLineOption[] options)
|
||||
{
|
||||
var usageInformation = new StringBuilder();
|
||||
usageInformation.AppendLine("Usage:");
|
||||
usageInformation.AppendLine();
|
||||
|
||||
var longestShortName = 0;
|
||||
var longestLongName = 0;
|
||||
var longestArgumentLength = 0;
|
||||
|
||||
foreach (var option in CommandLineOptions.ALL_OPTIONS)
|
||||
{
|
||||
if (option.ShortName != null && longestShortName < option.ShortName.Length)
|
||||
longestShortName = option.ShortName.Length;
|
||||
|
||||
if (option.LongName != null && longestLongName < option.LongName.Length)
|
||||
longestLongName = option.LongName.Length;
|
||||
|
||||
var argumentLength = GetOptionArgumentLength(option);
|
||||
if (longestArgumentLength < argumentLength)
|
||||
longestArgumentLength = argumentLength;
|
||||
}
|
||||
|
||||
var categories = CommandLineOptions.ALL_OPTIONS
|
||||
.Select(option => option.Category)
|
||||
.Distinct();
|
||||
|
||||
var firstCategory = true;
|
||||
foreach (var category in categories)
|
||||
{
|
||||
var optionsOfCategory = CommandLineOptions.ALL_OPTIONS
|
||||
.Where(option => category.Equals(option.Category));
|
||||
|
||||
if(!firstCategory)
|
||||
usageInformation.AppendLine();
|
||||
|
||||
if (!string.IsNullOrEmpty(category))
|
||||
{
|
||||
usageInformation.AppendLine($"== {category} ==");
|
||||
}
|
||||
|
||||
foreach (var option in optionsOfCategory)
|
||||
{
|
||||
if (option.ShortName != null)
|
||||
{
|
||||
usageInformation.Append($"-{option.ShortName}");
|
||||
usageInformation.Append(' ', longestShortName - option.ShortName.Length);
|
||||
|
||||
if (option.LongName != null)
|
||||
usageInformation.Append(", ");
|
||||
else
|
||||
usageInformation.Append(' ', 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
usageInformation.Append(' ', longestShortName + 1 + 2);
|
||||
}
|
||||
|
||||
if (option.LongName != null)
|
||||
{
|
||||
usageInformation.Append($"--{option.LongName}");
|
||||
usageInformation.Append(' ', longestLongName - option.LongName.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
usageInformation.Append(' ', longestLongName + 2);
|
||||
}
|
||||
|
||||
usageInformation.Append(' ');
|
||||
|
||||
var argumentLength = GetOptionArgumentLength(option);
|
||||
for(var i = 0; i < option.ParameterCount; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
usageInformation.Append(' ');
|
||||
|
||||
usageInformation.Append($"<{option.Parameters[i]}>");
|
||||
}
|
||||
|
||||
usageInformation.Append(' ', longestArgumentLength - argumentLength + 1);
|
||||
|
||||
usageInformation.Append(option.Description);
|
||||
|
||||
usageInformation.AppendLine();
|
||||
}
|
||||
|
||||
firstCategory = false;
|
||||
}
|
||||
|
||||
return usageInformation.ToString();
|
||||
}
|
||||
|
||||
private static int GetOptionArgumentLength(CommandLineOption option)
|
||||
{
|
||||
return option.ParameterCount * 2 // < and >
|
||||
+ option.Parameters.Select(s => s.Length).Sum() // Length of the argument name
|
||||
+ Math.Max(0, option.ParameterCount - 1); // One space between each argument
|
||||
}
|
||||
}
|
||||
}
|
109
src/ZoneCodeGenerator/Interface/CUI.cs
Normal file
109
src/ZoneCodeGenerator/Interface/CUI.cs
Normal file
@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using ZoneCodeGenerator.Generating;
|
||||
using ZoneCodeGenerator.Interface.Arguments;
|
||||
using ZoneCodeGenerator.Parsing.C_Header;
|
||||
using ZoneCodeGenerator.Parsing.CommandFile;
|
||||
|
||||
namespace ZoneCodeGenerator.Interface
|
||||
{
|
||||
class CUI
|
||||
{
|
||||
public bool Start(string[] args)
|
||||
{
|
||||
var argumentParser = new ArgumentParser(CommandLineOptions.ALL_OPTIONS);
|
||||
|
||||
if (args.Length == 0 || !argumentParser.ParseArguments(args))
|
||||
{
|
||||
PrintUsage();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_HELP))
|
||||
{
|
||||
PrintUsage();
|
||||
return true;
|
||||
}
|
||||
|
||||
var session = new CUISession();
|
||||
|
||||
if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_OUTPUT_FOLDER))
|
||||
{
|
||||
session.GeneratorOutputPath = argumentParser.GetValueForOption(CommandLineOptions.OPTION_OUTPUT_FOLDER);
|
||||
}
|
||||
|
||||
if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_CREATE))
|
||||
{
|
||||
session.SourceFilePath = argumentParser.GetValueForOption(CommandLineOptions.OPTION_CREATE);
|
||||
session.Repository = HeaderReader.ReadFile(session.SourceFilePath);
|
||||
|
||||
if (session.Repository == null)
|
||||
{
|
||||
Console.WriteLine($"Creating a database from header file '{argumentParser.GetValueForOption(CommandLineOptions.OPTION_CREATE)}' failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Parsing a c header is needed to perform any other action.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_EDITING_COMMANDS))
|
||||
{
|
||||
if (!CommandFileReader.ReadFile(argumentParser.GetValueForOption(CommandLineOptions.OPTION_EDITING_COMMANDS), session))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_PRINT))
|
||||
{
|
||||
var printer = new PrettyPrinter(session.Repository);
|
||||
printer.PrintAll();
|
||||
}
|
||||
|
||||
if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_GENERATE))
|
||||
{
|
||||
var generationArgs = argumentParser.GetParametersForOption(CommandLineOptions.OPTION_GENERATE);
|
||||
for (var i = 0; i < generationArgs.Count; i += CommandLineOptions.OPTION_GENERATE.ParameterCount)
|
||||
{
|
||||
var assetName = generationArgs[i];
|
||||
var preset = generationArgs[i + 1];
|
||||
|
||||
var assets = session.Repository.GetAllStructureInformation()
|
||||
.Where(inf => inf.IsAsset);
|
||||
|
||||
if (!assetName.Equals("*"))
|
||||
assets = assets.Where(inf =>
|
||||
inf.Type.FullName.Equals(assetName, StringComparison.CurrentCultureIgnoreCase));
|
||||
|
||||
if (!assets.Any())
|
||||
{
|
||||
Console.WriteLine($"Could not find asset '{assetName}'.");
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var asset in assets)
|
||||
{
|
||||
if (CodeGenerator.GenerateCodeForPreset(preset, asset, session))
|
||||
{
|
||||
Console.WriteLine($"Successfully generated code for asset '{asset.Type.FullName}' with preset '{preset}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Could not generate code for asset '{asset.Type.FullName}' with preset '{preset}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void PrintUsage()
|
||||
{
|
||||
Console.WriteLine(UsageInformation.FromCommandlineOptions(CommandLineOptions.ALL_OPTIONS));
|
||||
}
|
||||
}
|
||||
}
|
18
src/ZoneCodeGenerator/Interface/CUISession.cs
Normal file
18
src/ZoneCodeGenerator/Interface/CUISession.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Interface
|
||||
{
|
||||
class CUISession
|
||||
{
|
||||
public string Game { get; set; }
|
||||
public IDataRepository Repository { get; set; }
|
||||
public string GeneratorOutputPath { get; set; }
|
||||
public string SourceFilePath { get; set; }
|
||||
|
||||
public CUISession()
|
||||
{
|
||||
Repository = null;
|
||||
GeneratorOutputPath = ".";
|
||||
}
|
||||
}
|
||||
}
|
91
src/ZoneCodeGenerator/Interface/CommandLineOptions.cs
Normal file
91
src/ZoneCodeGenerator/Interface/CommandLineOptions.cs
Normal file
@ -0,0 +1,91 @@
|
||||
using ZoneCodeGenerator.Generating;
|
||||
using ZoneCodeGenerator.Interface.Arguments;
|
||||
|
||||
namespace ZoneCodeGenerator.Interface
|
||||
{
|
||||
static class CommandLineOptions
|
||||
{
|
||||
// ------
|
||||
// GENERAL
|
||||
// ------
|
||||
|
||||
public static readonly CommandLineOption OPTION_HELP = CommandLineOption.CommandLineOptionBuilder.Create()
|
||||
.WithShortName("?")
|
||||
.WithLongName("help")
|
||||
.WithDescription("Show usage.")
|
||||
.Build();
|
||||
|
||||
// ------
|
||||
// INPUT
|
||||
// ------
|
||||
private const string CategoryInput = "Input";
|
||||
|
||||
public static readonly CommandLineOption OPTION_CREATE = CommandLineOption.CommandLineOptionBuilder.Create()
|
||||
.WithShortName("h")
|
||||
.WithLongName("header")
|
||||
.WithDescription("Create a new database from the specified header file.")
|
||||
.WithCategory(CategoryInput)
|
||||
.WithParameter("headerFile")
|
||||
.Build();
|
||||
|
||||
// ------
|
||||
// EDITING
|
||||
// ------
|
||||
private const string CategoryEditing = "Editing";
|
||||
|
||||
public static readonly CommandLineOption OPTION_EDITING_COMMANDS = CommandLineOption.CommandLineOptionBuilder.Create()
|
||||
.WithShortName("e")
|
||||
.WithLongName("editing-commands")
|
||||
.WithDescription("Specifies the editing command file. Defaults to stdin.")
|
||||
.WithCategory(CategoryEditing)
|
||||
.WithParameter("commandFile")
|
||||
.Build();
|
||||
|
||||
// ------
|
||||
// OUTPUT
|
||||
// ------
|
||||
private const string CategoryOutput = "Output";
|
||||
|
||||
public static readonly CommandLineOption OPTION_OUTPUT_FOLDER = CommandLineOption.CommandLineOptionBuilder.Create()
|
||||
.WithShortName("o")
|
||||
.WithLongName("output")
|
||||
.WithDescription("Specify the folder to save the generate code files to. Defaults to the current directory.")
|
||||
.WithCategory(CategoryOutput)
|
||||
.WithParameter("outputPath")
|
||||
.Build();
|
||||
|
||||
public static readonly CommandLineOption OPTION_PRINT = CommandLineOption.CommandLineOptionBuilder.Create()
|
||||
.WithShortName("p")
|
||||
.WithLongName("print")
|
||||
.WithDescription("Print the loaded data.")
|
||||
.WithCategory(CategoryOutput)
|
||||
.Build();
|
||||
|
||||
public static readonly CommandLineOption OPTION_GENERATE = CommandLineOption.CommandLineOptionBuilder.Create()
|
||||
.WithShortName("g")
|
||||
.WithLongName("generate")
|
||||
.WithDescription($"Generates a specified asset/preset combination. Can be used multiple times. Available presets: {string.Join(", ", CodeGenerator.Presets)}")
|
||||
.WithCategory(CategoryOutput)
|
||||
.WithParameter("assetName")
|
||||
.WithParameter("preset")
|
||||
.Reusable()
|
||||
.Build();
|
||||
|
||||
public static readonly CommandLineOption[] ALL_OPTIONS =
|
||||
{
|
||||
// GENERAL
|
||||
OPTION_HELP,
|
||||
|
||||
// INPUT
|
||||
OPTION_CREATE,
|
||||
|
||||
// EDITING
|
||||
OPTION_EDITING_COMMANDS,
|
||||
|
||||
// OUTPUT
|
||||
OPTION_OUTPUT_FOLDER,
|
||||
OPTION_PRINT,
|
||||
OPTION_GENERATE,
|
||||
};
|
||||
}
|
||||
}
|
315
src/ZoneCodeGenerator/Interface/PrettyPrinter.cs
Normal file
315
src/ZoneCodeGenerator/Interface/PrettyPrinter.cs
Normal file
@ -0,0 +1,315 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Interface
|
||||
{
|
||||
class PrettyPrinter
|
||||
{
|
||||
private readonly IDataRepository dataRepository;
|
||||
|
||||
public PrettyPrinter(IDataRepository dataRepository)
|
||||
{
|
||||
this.dataRepository = dataRepository;
|
||||
}
|
||||
|
||||
public void PrintEnums()
|
||||
{
|
||||
var allEnums = dataRepository.GetAllEnums();
|
||||
var dataTypeEnums = allEnums.ToList();
|
||||
|
||||
Console.WriteLine($"{dataTypeEnums.Count} enums:");
|
||||
|
||||
foreach(var _enum in dataTypeEnums)
|
||||
{
|
||||
Console.WriteLine($" Name: {_enum.FullName}");
|
||||
Console.WriteLine($" Alignment: {_enum.Alignment}");
|
||||
Console.WriteLine($" Size: {_enum.Size}");
|
||||
|
||||
foreach(var member in _enum.Members)
|
||||
{
|
||||
Console.WriteLine($" {member.Name} = {member.Value}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintVariablePointerToArray(Variable variable)
|
||||
{
|
||||
var arraySize = new List<int>();
|
||||
var pointerDepth = 0;
|
||||
var referenceOffset = 0;
|
||||
|
||||
for (; referenceOffset < variable.VariableType.References.Count; referenceOffset++)
|
||||
{
|
||||
if (!(variable.VariableType.References[referenceOffset] is ReferenceTypePointer))
|
||||
break;
|
||||
|
||||
pointerDepth++;
|
||||
}
|
||||
|
||||
for (; referenceOffset < variable.VariableType.References.Count; referenceOffset++)
|
||||
{
|
||||
if (!(variable.VariableType.References[referenceOffset] is ReferenceTypeArray array))
|
||||
throw new Exception("Expected the rest of the references to be array references");
|
||||
|
||||
arraySize.Add(array.ArraySize);
|
||||
}
|
||||
|
||||
var memberBuilder = new StringBuilder();
|
||||
memberBuilder.Append(" ");
|
||||
memberBuilder.Append(variable.VariableType.Type.FullName);
|
||||
memberBuilder.Append('(');
|
||||
memberBuilder.Append('*', pointerDepth);
|
||||
memberBuilder.Append(variable.Name);
|
||||
memberBuilder.Append(')');
|
||||
|
||||
foreach (var array in arraySize)
|
||||
{
|
||||
memberBuilder.Append('[');
|
||||
memberBuilder.Append(array);
|
||||
memberBuilder.Append(']');
|
||||
}
|
||||
|
||||
Console.WriteLine(memberBuilder.ToString());
|
||||
}
|
||||
|
||||
private static void PrintVariableArrayOfPointers(Variable variable)
|
||||
{
|
||||
var arraySize = new List<int>();
|
||||
var pointerDepth = 0;
|
||||
var referenceOffset = 0;
|
||||
|
||||
for (; referenceOffset < variable.VariableType.References.Count; referenceOffset++)
|
||||
{
|
||||
if (!(variable.VariableType.References[referenceOffset] is ReferenceTypeArray array))
|
||||
break;
|
||||
|
||||
arraySize.Add(array.ArraySize);
|
||||
}
|
||||
|
||||
for (; referenceOffset < variable.VariableType.References.Count; referenceOffset++)
|
||||
{
|
||||
if (!(variable.VariableType.References[referenceOffset] is ReferenceTypePointer))
|
||||
throw new Exception("Expected the rest of the references to be pointer references");
|
||||
|
||||
pointerDepth++;
|
||||
}
|
||||
|
||||
var memberBuilder = new StringBuilder();
|
||||
memberBuilder.Append(" ");
|
||||
memberBuilder.Append(variable.VariableType.Type.FullName);
|
||||
memberBuilder.Append('*', pointerDepth);
|
||||
memberBuilder.Append(" ");
|
||||
memberBuilder.Append(variable.Name);
|
||||
|
||||
foreach (var array in arraySize)
|
||||
{
|
||||
memberBuilder.Append('[');
|
||||
memberBuilder.Append(array);
|
||||
memberBuilder.Append(']');
|
||||
}
|
||||
|
||||
Console.WriteLine(memberBuilder.ToString());
|
||||
}
|
||||
|
||||
private static void PrintVariable(Variable variable)
|
||||
{
|
||||
if (variable.VariableType.References.Count == 0)
|
||||
{
|
||||
Console.WriteLine($" {variable.VariableType.Type.FullName} {variable.Name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (variable.VariableType.References[0] is ReferenceTypePointer &&
|
||||
variable.VariableType.References.OfType<ReferenceTypeArray>().Any())
|
||||
{
|
||||
PrintVariablePointerToArray(variable);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintVariableArrayOfPointers(variable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void PrintStructs()
|
||||
{
|
||||
var allStructs = dataRepository.GetAllStructs();
|
||||
var dataTypeStructs = allStructs.ToList();
|
||||
|
||||
Console.WriteLine($"{dataTypeStructs.Count} structs:");
|
||||
|
||||
foreach(var _struct in dataTypeStructs)
|
||||
{
|
||||
Console.WriteLine($" Name: {_struct.FullName}");
|
||||
Console.WriteLine($" Alignment: {_struct.Alignment}");
|
||||
Console.WriteLine($" Size: {_struct.Size}");
|
||||
|
||||
foreach(var member in _struct.Members)
|
||||
PrintVariable(member);
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void PrintUnions()
|
||||
{
|
||||
var allUnions = dataRepository.GetAllUnions();
|
||||
var dataTypeUnions = allUnions.ToList();
|
||||
|
||||
Console.WriteLine($"{dataTypeUnions.Count} unions:");
|
||||
|
||||
foreach(var union in dataTypeUnions)
|
||||
{
|
||||
Console.WriteLine($" Name: {union.FullName}");
|
||||
Console.WriteLine($" Alignment: {union.Alignment}");
|
||||
Console.WriteLine($" Size: {union.Size}");
|
||||
|
||||
foreach(var member in union.Members)
|
||||
PrintVariable(member);
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintTypedefPointerToArray(DataTypeTypedef typedef)
|
||||
{
|
||||
var arraySize = new List<int>();
|
||||
var pointerDepth = 0;
|
||||
var referenceOffset = 0;
|
||||
|
||||
for (; referenceOffset < typedef.TypeDefinition.References.Count; referenceOffset++)
|
||||
{
|
||||
if (!(typedef.TypeDefinition.References[referenceOffset] is ReferenceTypePointer))
|
||||
break;
|
||||
|
||||
pointerDepth++;
|
||||
}
|
||||
|
||||
for (; referenceOffset < typedef.TypeDefinition.References.Count; referenceOffset++)
|
||||
{
|
||||
if (!(typedef.TypeDefinition.References[referenceOffset] is ReferenceTypeArray array))
|
||||
throw new Exception("Expected the rest of the references to be array references");
|
||||
|
||||
arraySize.Add(array.ArraySize);
|
||||
}
|
||||
|
||||
var memberBuilder = new StringBuilder();
|
||||
memberBuilder.Append(" ");
|
||||
memberBuilder.Append(typedef.TypeDefinition.Type.FullName);
|
||||
memberBuilder.Append('(');
|
||||
memberBuilder.Append('*', pointerDepth);
|
||||
memberBuilder.Append(')');
|
||||
|
||||
foreach (var array in arraySize)
|
||||
{
|
||||
memberBuilder.Append('[');
|
||||
memberBuilder.Append(array);
|
||||
memberBuilder.Append(']');
|
||||
}
|
||||
|
||||
Console.WriteLine(memberBuilder.ToString());
|
||||
}
|
||||
|
||||
private static void PrintTypedefArrayOfPointers(DataTypeTypedef typedef)
|
||||
{
|
||||
var arraySize = new List<int>();
|
||||
var pointerDepth = 0;
|
||||
var referenceOffset = 0;
|
||||
|
||||
for (; referenceOffset < typedef.TypeDefinition.References.Count; referenceOffset++)
|
||||
{
|
||||
if (!(typedef.TypeDefinition.References[referenceOffset] is ReferenceTypeArray array))
|
||||
break;
|
||||
|
||||
arraySize.Add(array.ArraySize);
|
||||
}
|
||||
|
||||
for (; referenceOffset < typedef.TypeDefinition.References.Count; referenceOffset++)
|
||||
{
|
||||
if (!(typedef.TypeDefinition.References[referenceOffset] is ReferenceTypePointer))
|
||||
throw new Exception("Expected the rest of the references to be pointer references");
|
||||
|
||||
pointerDepth++;
|
||||
}
|
||||
|
||||
var memberBuilder = new StringBuilder();
|
||||
memberBuilder.Append(" ");
|
||||
memberBuilder.Append(typedef.TypeDefinition.Type.FullName);
|
||||
memberBuilder.Append('*', pointerDepth);
|
||||
|
||||
foreach (var array in arraySize)
|
||||
{
|
||||
memberBuilder.Append('[');
|
||||
memberBuilder.Append(array);
|
||||
memberBuilder.Append(']');
|
||||
}
|
||||
|
||||
Console.WriteLine(memberBuilder.ToString());
|
||||
}
|
||||
|
||||
public void PrintTypedefs()
|
||||
{
|
||||
var allTypedefs = dataRepository.GetAllTypedefs();
|
||||
var dataTypeTypedefs = allTypedefs.ToList();
|
||||
|
||||
Console.WriteLine($"{dataTypeTypedefs.Count} typedefs:");
|
||||
|
||||
foreach (var typeDef in dataTypeTypedefs)
|
||||
{
|
||||
Console.WriteLine($" Name: {typeDef.FullName}");
|
||||
Console.WriteLine($" Alignment: {typeDef.Alignment}");
|
||||
Console.WriteLine($" Size: {typeDef.Size}");
|
||||
|
||||
if (typeDef.TypeDefinition.References.Count == 0)
|
||||
{
|
||||
Console.WriteLine($" {typeDef.TypeDefinition.Type.FullName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (typeDef.TypeDefinition.References[0] is ReferenceTypePointer &&
|
||||
typeDef.TypeDefinition.References.OfType<ReferenceTypeArray>().Any())
|
||||
{
|
||||
PrintTypedefPointerToArray(typeDef);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintTypedefArrayOfPointers(typeDef);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void PrintAll()
|
||||
{
|
||||
PrintEnums();
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("==========================================================================================================");
|
||||
Console.WriteLine();
|
||||
|
||||
PrintStructs();
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("==========================================================================================================");
|
||||
Console.WriteLine();
|
||||
|
||||
PrintUnions();
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("==========================================================================================================");
|
||||
Console.WriteLine();
|
||||
|
||||
PrintTypedefs();
|
||||
}
|
||||
}
|
||||
}
|
11
src/ZoneCodeGenerator/LoadingException.cs
Normal file
11
src/ZoneCodeGenerator/LoadingException.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace ZoneCodeGenerator
|
||||
{
|
||||
class LoadingException : Exception
|
||||
{
|
||||
public LoadingException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
11
src/ZoneCodeGenerator/Parsing/C_Header/BlockType.cs
Normal file
11
src/ZoneCodeGenerator/Parsing/C_Header/BlockType.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header
|
||||
{
|
||||
enum BlockType
|
||||
{
|
||||
None,
|
||||
Enum,
|
||||
Namespace,
|
||||
Struct,
|
||||
Union
|
||||
}
|
||||
}
|
25
src/ZoneCodeGenerator/Parsing/C_Header/Blocks/Block.cs
Normal file
25
src/ZoneCodeGenerator/Parsing/C_Header/Blocks/Block.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
|
||||
{
|
||||
abstract class Block
|
||||
{
|
||||
protected readonly IHeaderParserState State;
|
||||
public BlockType Type { get; }
|
||||
|
||||
protected Block(IHeaderParserState headerParserState, BlockType type)
|
||||
{
|
||||
State = headerParserState;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public abstract IEnumerable<ITokenTest<IHeaderParserState>> GetAvailableTests();
|
||||
|
||||
public abstract void OnOpen();
|
||||
|
||||
public abstract void OnClose();
|
||||
|
||||
public abstract void OnChildBlockClose(Block childBlock);
|
||||
}
|
||||
}
|
114
src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockEnum.cs
Normal file
114
src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockEnum.cs
Normal file
@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Tests;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
|
||||
{
|
||||
class BlockEnum : Block, INameAssignable, IVariableBlock
|
||||
{
|
||||
private readonly ITokenTest<IHeaderParserState>[] tests =
|
||||
{
|
||||
new TestEnumMember(),
|
||||
new TestCloseBlock(true)
|
||||
};
|
||||
|
||||
public string Name { get; }
|
||||
public string AssignedName { get; private set; }
|
||||
public string Namespace { get; private set; }
|
||||
public DataTypeBaseType ParentType { get; }
|
||||
public bool IsTypedef { get; }
|
||||
public List<EnumMember> Members { get; }
|
||||
|
||||
private DataTypeEnum _enum;
|
||||
|
||||
public BlockEnum(IHeaderParserState headerParserState, string name, DataTypeBaseType parentType, bool isTypedef) : base(headerParserState, BlockType.Enum)
|
||||
{
|
||||
Name = name;
|
||||
ParentType = parentType;
|
||||
IsTypedef = isTypedef;
|
||||
Members = new List<EnumMember>();
|
||||
}
|
||||
|
||||
public override IEnumerable<ITokenTest<IHeaderParserState>> GetAvailableTests()
|
||||
{
|
||||
return tests;
|
||||
}
|
||||
|
||||
public override void OnOpen()
|
||||
{
|
||||
Namespace = State.CurrentNamespace.ToString();
|
||||
|
||||
State.CurrentNamespace.Push(Name);
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
var poppedNamespaceName = State.CurrentNamespace.Pop();
|
||||
|
||||
if (!Name.Equals(poppedNamespaceName))
|
||||
throw new Exception($"Popped namespace '{poppedNamespaceName}' does not equal name of union block '{Name}'");
|
||||
|
||||
_enum = new DataTypeEnum(Namespace, Name, ParentType);
|
||||
|
||||
_enum.Members.AddRange(Members);
|
||||
|
||||
State.AddDataType(_enum);
|
||||
|
||||
if (IsTypedef)
|
||||
{
|
||||
var typeDeclaration = new TypeDeclaration(_enum, new List<ReferenceType>());
|
||||
var typedef = new DataTypeTypedef(Namespace, AssignedName, typeDeclaration);
|
||||
|
||||
State.AddDataType(typedef);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnChildBlockClose(Block childBlock)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void AssignName(string nameAssignment)
|
||||
{
|
||||
AssignedName = nameAssignment;
|
||||
}
|
||||
|
||||
public virtual void AddMember(EnumMember enumMember)
|
||||
{
|
||||
Members.Add(enumMember);
|
||||
}
|
||||
|
||||
public virtual EnumMember FindMember(string enumMemberName)
|
||||
{
|
||||
return Members.Find(member => member.Name.Equals(enumMemberName));
|
||||
}
|
||||
|
||||
public virtual long GetNextEnumValue()
|
||||
{
|
||||
var nextValue = 0L;
|
||||
|
||||
if (Members.Count > 0)
|
||||
{
|
||||
nextValue = Members[Members.Count - 1].Value + 1;
|
||||
}
|
||||
|
||||
return nextValue;
|
||||
}
|
||||
|
||||
public bool DefinesVariable()
|
||||
{
|
||||
return !IsTypedef && !string.IsNullOrEmpty(AssignedName) && _enum != null;
|
||||
}
|
||||
|
||||
public Variable GetDefinedVariable()
|
||||
{
|
||||
if (!DefinesVariable())
|
||||
return null;
|
||||
|
||||
var typeDeclaration = new TypeDeclaration(_enum, new List<ReferenceType>());
|
||||
return new Variable(AssignedName, typeDeclaration);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Tests;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
|
||||
{
|
||||
class BlockNamespace : Block
|
||||
{
|
||||
private readonly ITokenTest<IHeaderParserState>[] tests =
|
||||
{
|
||||
new TestNamespace(),
|
||||
new TestEnum(),
|
||||
new TestStruct(),
|
||||
new TestUnion(),
|
||||
new TestTypedef(),
|
||||
new TestForwardDecl(),
|
||||
new TestCloseBlock()
|
||||
};
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public BlockNamespace(IHeaderParserState headerParserState, string namespaceName) : base(headerParserState, BlockType.Namespace)
|
||||
{
|
||||
Name = namespaceName;
|
||||
}
|
||||
|
||||
public override IEnumerable<ITokenTest<IHeaderParserState>> GetAvailableTests()
|
||||
{
|
||||
return tests;
|
||||
}
|
||||
|
||||
public override void OnOpen()
|
||||
{
|
||||
State.CurrentNamespace.Push(Name);
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
var poppedNamespaceName = State.CurrentNamespace.Pop();
|
||||
|
||||
if (!Name.Equals(poppedNamespaceName))
|
||||
throw new Exception($"Popped namespace '{poppedNamespaceName}' does not equal name of namespace block '{Name}'");
|
||||
}
|
||||
|
||||
public override void OnChildBlockClose(Block childBlock)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
44
src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockNone.cs
Normal file
44
src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockNone.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System.Collections.Generic;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Tests;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
|
||||
{
|
||||
class BlockNone : Block
|
||||
{
|
||||
private readonly ITokenTest<IHeaderParserState>[] tests =
|
||||
{
|
||||
new TestNamespace(),
|
||||
new TestEnum(),
|
||||
new TestStruct(),
|
||||
new TestUnion(),
|
||||
new TestTypedef(),
|
||||
new TestForwardDecl()
|
||||
};
|
||||
|
||||
public BlockNone(IHeaderParserState headerParserState) : base(headerParserState, BlockType.None)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override IEnumerable<ITokenTest<IHeaderParserState>> GetAvailableTests()
|
||||
{
|
||||
return tests;
|
||||
}
|
||||
|
||||
public override void OnOpen()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public override void OnChildBlockClose(Block childBlock)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
117
src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockStruct.cs
Normal file
117
src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockStruct.cs
Normal file
@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Tests;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
|
||||
{
|
||||
class BlockStruct : Block, INameAssignable, IVariableHolder, IVariableBlock
|
||||
{
|
||||
private readonly ITokenTest<IHeaderParserState>[] tests =
|
||||
{
|
||||
new TestStruct(),
|
||||
new TestEnum(),
|
||||
new TestUnion(),
|
||||
new TestVariable(),
|
||||
new TestCloseBlock(true)
|
||||
};
|
||||
|
||||
public string Name { get; }
|
||||
public string AssignedName { get; private set; }
|
||||
public string Namespace { get; private set; }
|
||||
public bool IsTypedef { get; }
|
||||
public int? CustomAlignment { get; set; }
|
||||
public int Pack { get; private set; }
|
||||
public List<Variable> Variables { get; }
|
||||
|
||||
private DataTypeStruct _struct;
|
||||
private DataTypeTypedef typedef;
|
||||
|
||||
public BlockStruct(IHeaderParserState headerParserState, string name, bool isTypedef) : base(headerParserState, BlockType.Struct)
|
||||
{
|
||||
Name = name;
|
||||
IsTypedef = isTypedef;
|
||||
Variables = new List<Variable>();
|
||||
AssignedName = "";
|
||||
_struct = null;
|
||||
typedef = null;
|
||||
}
|
||||
|
||||
public override IEnumerable<ITokenTest<IHeaderParserState>> GetAvailableTests()
|
||||
{
|
||||
return tests;
|
||||
}
|
||||
|
||||
public override void OnOpen()
|
||||
{
|
||||
Pack = State.CurrentPack;
|
||||
|
||||
Namespace = State.CurrentNamespace.ToString();
|
||||
|
||||
State.CurrentNamespace.Push(Name);
|
||||
|
||||
State.AddForwardDeclaration(new ForwardDeclaration(Namespace, Name, DataTypeType.Struct));
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
var poppedNamespaceName = State.CurrentNamespace.Pop();
|
||||
|
||||
if (!Name.Equals(poppedNamespaceName))
|
||||
throw new Exception($"Popped namespace '{poppedNamespaceName}' does not equal name of struct block '{Name}'");
|
||||
|
||||
_struct = new DataTypeStruct(Namespace, Name, Pack);
|
||||
|
||||
_struct.Members.AddRange(Variables);
|
||||
|
||||
State.AddDataType(_struct);
|
||||
|
||||
if (IsTypedef)
|
||||
{
|
||||
var typeDeclaration = new TypeDeclaration(_struct, new List<ReferenceType>());
|
||||
typedef = new DataTypeTypedef(Namespace, AssignedName, typeDeclaration);
|
||||
|
||||
State.AddDataType(typedef);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnChildBlockClose(Block childBlock)
|
||||
{
|
||||
if (childBlock is IVariableBlock variableBlock)
|
||||
{
|
||||
AddVariable(variableBlock.GetDefinedVariable());
|
||||
}
|
||||
}
|
||||
|
||||
public void AssignName(string nameAssignment)
|
||||
{
|
||||
AssignedName = nameAssignment;
|
||||
}
|
||||
|
||||
public void AddVariable(Variable variable)
|
||||
{
|
||||
Variables.Add(variable);
|
||||
}
|
||||
|
||||
public Variable GetDefinedVariable()
|
||||
{
|
||||
var name = "";
|
||||
DataType dataType = _struct;
|
||||
|
||||
if (!IsTypedef)
|
||||
name = AssignedName;
|
||||
else
|
||||
dataType = typedef;
|
||||
|
||||
var typeDeclaration = new TypeDeclaration(dataType, new List<ReferenceType>());
|
||||
return new Variable(name, typeDeclaration);
|
||||
}
|
||||
|
||||
public void Inherit(DataTypeStruct parent)
|
||||
{
|
||||
foreach(var variable in parent.Members)
|
||||
AddVariable(variable);
|
||||
}
|
||||
}
|
||||
}
|
120
src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockUnion.cs
Normal file
120
src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockUnion.cs
Normal file
@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Tests;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
|
||||
{
|
||||
class BlockUnion : Block, INameAssignable, IVariableHolder, IVariableBlock
|
||||
{
|
||||
private readonly ITokenTest<IHeaderParserState>[] tests =
|
||||
{
|
||||
new TestStruct(),
|
||||
new TestEnum(),
|
||||
new TestUnion(),
|
||||
new TestVariable(),
|
||||
new TestCloseBlock(true)
|
||||
};
|
||||
|
||||
public string Name { get; }
|
||||
public string AssignedName { get; private set; }
|
||||
public string Namespace { get; private set; }
|
||||
public bool IsTypedef { get; }
|
||||
public int? CustomAlignment { get; set; }
|
||||
public int Pack { get; private set; }
|
||||
public List<Variable> Variables { get; }
|
||||
|
||||
private DataTypeUnion union;
|
||||
private DataTypeTypedef typedef;
|
||||
|
||||
public BlockUnion(IHeaderParserState headerParserState, string name, bool isTypedef) : base(headerParserState, BlockType.Union)
|
||||
{
|
||||
Name = name;
|
||||
IsTypedef = isTypedef;
|
||||
Variables = new List<Variable>();
|
||||
CustomAlignment = null;
|
||||
AssignedName = "";
|
||||
union = null;
|
||||
typedef = null;
|
||||
}
|
||||
|
||||
public override IEnumerable<ITokenTest<IHeaderParserState>> GetAvailableTests()
|
||||
{
|
||||
return tests;
|
||||
}
|
||||
|
||||
public override void OnOpen()
|
||||
{
|
||||
Namespace = State.CurrentNamespace.ToString();
|
||||
Pack = State.CurrentPack;
|
||||
|
||||
State.CurrentNamespace.Push(Name);
|
||||
|
||||
State.AddForwardDeclaration(new ForwardDeclaration(Namespace, Name, DataTypeType.Union));
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
var poppedNamespaceName = State.CurrentNamespace.Pop();
|
||||
|
||||
if (!Name.Equals(poppedNamespaceName))
|
||||
throw new Exception($"Popped namespace '{poppedNamespaceName}' does not equal name of union block '{Name}'");
|
||||
|
||||
union = new DataTypeUnion(Namespace, Name, Pack)
|
||||
{
|
||||
AlignmentOverride = CustomAlignment
|
||||
};
|
||||
|
||||
union.Members.AddRange(Variables);
|
||||
|
||||
State.AddDataType(union);
|
||||
|
||||
if (IsTypedef)
|
||||
{
|
||||
var typeDeclaration = new TypeDeclaration(union, new List<ReferenceType>());
|
||||
typedef = new DataTypeTypedef(Namespace, AssignedName, typeDeclaration);
|
||||
|
||||
State.AddDataType(typedef);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnChildBlockClose(Block childBlock)
|
||||
{
|
||||
if (childBlock is IVariableBlock variableBlock)
|
||||
{
|
||||
AddVariable(variableBlock.GetDefinedVariable());
|
||||
}
|
||||
}
|
||||
|
||||
public void AssignName(string nameAssignment)
|
||||
{
|
||||
AssignedName = nameAssignment;
|
||||
}
|
||||
|
||||
public void AddVariable(Variable variable)
|
||||
{
|
||||
Variables.Add(variable);
|
||||
}
|
||||
|
||||
public Variable GetDefinedVariable()
|
||||
{
|
||||
var name = "";
|
||||
DataType dataType = union;
|
||||
|
||||
if (!IsTypedef)
|
||||
name = AssignedName;
|
||||
else
|
||||
dataType = typedef;
|
||||
|
||||
var typeDeclaration = new TypeDeclaration(dataType, new List<ReferenceType>());
|
||||
return new Variable(name, typeDeclaration);
|
||||
}
|
||||
|
||||
public void Inherit(DataTypeUnion parent)
|
||||
{
|
||||
foreach(var variable in parent.Members)
|
||||
AddVariable(variable);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
|
||||
{
|
||||
interface INameAssignable
|
||||
{
|
||||
void AssignName(string nameAssignment);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using ZoneCodeGenerator.Domain;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
|
||||
{
|
||||
interface IVariableBlock
|
||||
{
|
||||
Variable GetDefinedVariable();
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using ZoneCodeGenerator.Domain;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
|
||||
{
|
||||
interface IVariableHolder
|
||||
{
|
||||
void AddVariable(Variable variable);
|
||||
}
|
||||
}
|
79
src/ZoneCodeGenerator/Parsing/C_Header/HeaderReader.cs
Normal file
79
src/ZoneCodeGenerator/Parsing/C_Header/HeaderReader.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Impl;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.PostProcessor;
|
||||
using ZoneCodeGenerator.Parsing.Impl;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header
|
||||
{
|
||||
static class HeaderReader
|
||||
{
|
||||
private static readonly IDataPostProcessor[] postProcessors =
|
||||
{
|
||||
new PostProcessorUsages(),
|
||||
};
|
||||
|
||||
public static IDataRepository ReadFile(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (IIncludingParsingStream streamFileSystem = new IncludingStreamFileSystem(path))
|
||||
{
|
||||
var state = new HeaderParserState();
|
||||
IDataRepository dataRepository;
|
||||
|
||||
using (IParsingFileStream preprocessorStream = new Preprocessor(streamFileSystem, state))
|
||||
{
|
||||
var lexer = new Lexer(preprocessorStream);
|
||||
var parser = new Parser<HeaderParserState>(state, lexer);
|
||||
|
||||
if (!parser.Parse())
|
||||
return null;
|
||||
|
||||
dataRepository = new InMemoryDataRepository();
|
||||
try
|
||||
{
|
||||
state.FinishAndSaveTo(dataRepository);
|
||||
}
|
||||
catch (LoadingException e)
|
||||
{
|
||||
PrintFinishingError(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
preprocessorStream.Close();
|
||||
streamFileSystem.Close();
|
||||
|
||||
}
|
||||
|
||||
if (!PostProcessRepository(dataRepository))
|
||||
{
|
||||
Console.WriteLine("Postprocessing data failed.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return dataRepository;
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool PostProcessRepository(IDataRepository repository)
|
||||
{
|
||||
return postProcessors.All(postProcessor => postProcessor.PostProcess(repository));
|
||||
}
|
||||
|
||||
private static void PrintFinishingError(LoadingException e)
|
||||
{
|
||||
Console.WriteLine("Parsing failed.");
|
||||
|
||||
Console.WriteLine(e.Message);
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
28
src/ZoneCodeGenerator/Parsing/C_Header/IHeaderParserState.cs
Normal file
28
src/ZoneCodeGenerator/Parsing/C_Header/IHeaderParserState.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header
|
||||
{
|
||||
interface IHeaderParserState : IParserState<IHeaderParserState>
|
||||
{
|
||||
Namespace CurrentNamespace { get; }
|
||||
int CurrentPack { get; }
|
||||
Block CurrentBlock { get; }
|
||||
Block PreviousBlock { get; }
|
||||
|
||||
void PushPack(int pack);
|
||||
int PopPack();
|
||||
|
||||
void PushBlock(Block block);
|
||||
Block PopBlock();
|
||||
|
||||
void AddDataType(DataType dataType);
|
||||
void AddForwardDeclaration(ForwardDeclaration forwardDeclaration);
|
||||
|
||||
DataType FindType(string typename);
|
||||
EnumMember FindEnumMember(string enumMemberName);
|
||||
|
||||
void FinishAndSaveTo(IDataRepository dataRepository);
|
||||
}
|
||||
}
|
208
src/ZoneCodeGenerator/Parsing/C_Header/Impl/HeaderParserState.cs
Normal file
208
src/ZoneCodeGenerator/Parsing/C_Header/Impl/HeaderParserState.cs
Normal file
@ -0,0 +1,208 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Impl
|
||||
{
|
||||
class HeaderParserState : IHeaderParserState
|
||||
{
|
||||
private const int DefaultPack = 8;
|
||||
|
||||
private readonly Block defaultBlock;
|
||||
private readonly Stack<int> packStack;
|
||||
private readonly Stack<Block> blockStack;
|
||||
|
||||
private readonly Dictionary<string, DataType> dataTypes;
|
||||
private readonly Dictionary<string, ForwardDeclaration> forwardDeclarations;
|
||||
|
||||
public Namespace CurrentNamespace { get; }
|
||||
|
||||
public HeaderParserState()
|
||||
{
|
||||
defaultBlock = new BlockNone(this);
|
||||
packStack = new Stack<int>();
|
||||
blockStack = new Stack<Block>();
|
||||
|
||||
dataTypes = new Dictionary<string, DataType>();
|
||||
forwardDeclarations = new Dictionary<string, ForwardDeclaration>();
|
||||
CurrentNamespace = new Namespace();
|
||||
}
|
||||
|
||||
public int CurrentPack => packStack.Count == 0 ? DefaultPack : packStack.Peek();
|
||||
|
||||
public Block CurrentBlock => blockStack.Count == 0 ? defaultBlock : blockStack.Peek();
|
||||
|
||||
public Block PreviousBlock => blockStack.Count < 2 ? defaultBlock : blockStack.ElementAt(1);
|
||||
|
||||
public void PushPack(int pack)
|
||||
{
|
||||
packStack.Push(pack);
|
||||
}
|
||||
|
||||
public int PopPack()
|
||||
{
|
||||
return packStack.Pop();
|
||||
}
|
||||
|
||||
public void PushBlock(Block block)
|
||||
{
|
||||
block.OnOpen();
|
||||
blockStack.Push(block);
|
||||
}
|
||||
|
||||
public Block PopBlock()
|
||||
{
|
||||
var block = blockStack.Pop();
|
||||
|
||||
block.OnClose();
|
||||
CurrentBlock.OnChildBlockClose(block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
public void AddDataType(DataType dataType)
|
||||
{
|
||||
if (dataTypes.ContainsKey(dataType.FullName))
|
||||
throw new ParserException($"Type '{dataType.FullName}' is already defined.");
|
||||
|
||||
dataTypes.Add(dataType.FullName, dataType);
|
||||
}
|
||||
|
||||
public void AddForwardDeclaration(ForwardDeclaration forwardDeclaration)
|
||||
{
|
||||
if (forwardDeclarations.ContainsKey(forwardDeclaration.FullName))
|
||||
{
|
||||
var existingForwardDeclaration = forwardDeclarations[forwardDeclaration.FullName];
|
||||
|
||||
if(existingForwardDeclaration.Type != forwardDeclaration.Type)
|
||||
throw new ParserException($"Forward declaration of type '{forwardDeclaration.FullName}' already done with different type.");
|
||||
}
|
||||
else
|
||||
{
|
||||
forwardDeclarations.Add(forwardDeclaration.FullName, forwardDeclaration);
|
||||
}
|
||||
}
|
||||
|
||||
public DataType FindType(string typename)
|
||||
{
|
||||
var currentNamespaceTypename = Namespace.Combine(CurrentNamespace, typename);
|
||||
|
||||
var baseType = DataTypeBaseType.BASE_TYPES.FirstOrDefault(databaseBaseType => databaseBaseType.Name.Equals(typename));
|
||||
|
||||
if (baseType != null)
|
||||
return baseType;
|
||||
|
||||
if (dataTypes.ContainsKey(typename))
|
||||
{
|
||||
return dataTypes[typename];
|
||||
}
|
||||
|
||||
if (dataTypes.ContainsKey(currentNamespaceTypename))
|
||||
{
|
||||
return dataTypes[currentNamespaceTypename];
|
||||
}
|
||||
|
||||
if (forwardDeclarations.ContainsKey(typename))
|
||||
{
|
||||
return forwardDeclarations[typename];
|
||||
}
|
||||
|
||||
if (forwardDeclarations.ContainsKey(currentNamespaceTypename))
|
||||
{
|
||||
return forwardDeclarations[currentNamespaceTypename];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public EnumMember FindEnumMember(string enumMemberName)
|
||||
{
|
||||
foreach(var block in blockStack)
|
||||
{
|
||||
if (!(block is BlockEnum blockEnum)) continue;
|
||||
|
||||
var foundMember = blockEnum.FindMember(enumMemberName);
|
||||
|
||||
if (foundMember != null)
|
||||
return foundMember;
|
||||
}
|
||||
|
||||
foreach (var dataType in dataTypes)
|
||||
{
|
||||
if (!(dataType.Value is DataTypeEnum _enum))
|
||||
continue;
|
||||
|
||||
var foundMember = _enum.Members.Find(member => member.Name.Equals(enumMemberName));
|
||||
|
||||
if (foundMember != null)
|
||||
return foundMember;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ResolveForwardDeclarations()
|
||||
{
|
||||
foreach(var forwardDeclaration in forwardDeclarations.Values)
|
||||
{
|
||||
var foundType = FindType(forwardDeclaration.FullName);
|
||||
|
||||
if (foundType == null || foundType is ForwardDeclaration)
|
||||
throw new ParserException($"Type {forwardDeclaration.FullName} was declared but not defined.");
|
||||
|
||||
forwardDeclaration.ForwardedType = foundType;
|
||||
}
|
||||
|
||||
foreach (var dataType in dataTypes.Values)
|
||||
{
|
||||
if (!(dataType is DataTypeWithMembers dataTypeWithMembers)) continue;
|
||||
|
||||
foreach (var variable in dataTypeWithMembers.Members)
|
||||
{
|
||||
if (variable.VariableType.Type is ForwardDeclaration forwardDeclaration)
|
||||
variable.VariableType.Type = forwardDeclaration.ForwardedType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void FinishAndSaveTo(IDataRepository dataRepository)
|
||||
{
|
||||
if(blockStack.Count > 0)
|
||||
throw new ParserException($"Parsing finished but {blockStack.Count} blocks were not closed.");
|
||||
|
||||
ResolveForwardDeclarations();
|
||||
|
||||
foreach (var dataType in dataTypes.Values)
|
||||
{
|
||||
switch (dataType)
|
||||
{
|
||||
case DataTypeEnum _enum:
|
||||
dataRepository.Add(_enum);
|
||||
break;
|
||||
case DataTypeStruct _struct:
|
||||
_struct.FinalizeDataType();
|
||||
dataRepository.Add(_struct);
|
||||
break;
|
||||
case DataTypeTypedef typedef:
|
||||
dataRepository.Add(typedef);
|
||||
break;
|
||||
case DataTypeUnion union:
|
||||
union.FinalizeDataType();
|
||||
dataRepository.Add(union);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(dataType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ITokenTest<IHeaderParserState>> GetTests()
|
||||
{
|
||||
return CurrentBlock.GetAvailableTests();
|
||||
}
|
||||
}
|
||||
}
|
127
src/ZoneCodeGenerator/Parsing/C_Header/Impl/Preprocessor.cs
Normal file
127
src/ZoneCodeGenerator/Parsing/C_Header/Impl/Preprocessor.cs
Normal file
@ -0,0 +1,127 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using ZoneCodeGenerator.Parsing.Impl;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Impl
|
||||
{
|
||||
class Preprocessor : IParsingFileStream
|
||||
{
|
||||
private static readonly Regex packPushRegex = new Regex(@"^\s*#pragma\s+pack\s*\(\s*push\s*,\s*(\d+)\s*\)\s*$");
|
||||
private static readonly Regex packPopRegex = new Regex(@"^\s*#pragma\s+pack\s*\(\s*pop\s*\)\s*$");
|
||||
private static readonly Regex defineRegex = new Regex(@"^\s*#define\s*(\w+)(?:\s*(.*))?$");
|
||||
private static readonly Regex undefRegex = new Regex(@"^\s*#undef\s*(\w+)\s*$");
|
||||
private static readonly Regex includeRegex = new Regex(@"^\s*#include\s*(?:\""(.*)\""|\<(.*)\>)\s*$");
|
||||
|
||||
private readonly IIncludingParsingStream streamFileSystem;
|
||||
private readonly IHeaderParserState state;
|
||||
private readonly ICommentProcessor commentProcessor;
|
||||
|
||||
private readonly Dictionary<string, string> defines;
|
||||
|
||||
public bool EndOfStream => streamFileSystem.EndOfStream;
|
||||
public string Filename => streamFileSystem.Filename;
|
||||
public int Line => streamFileSystem.Line;
|
||||
|
||||
public Preprocessor(IIncludingParsingStream includingParsingStream, IHeaderParserState state)
|
||||
{
|
||||
streamFileSystem = includingParsingStream;
|
||||
this.state = state;
|
||||
defines = new Dictionary<string, string>();
|
||||
commentProcessor = new CommentProcessor();
|
||||
}
|
||||
|
||||
private void ParseCompilerExpression(string line)
|
||||
{
|
||||
Match packPush = packPushRegex.Match(line.ToLower());
|
||||
if(packPush.Success)
|
||||
{
|
||||
state.PushPack(int.Parse(packPush.Groups[1].Value));
|
||||
return;
|
||||
}
|
||||
|
||||
Match packPop = packPopRegex.Match(line.ToLower());
|
||||
if(packPop.Success)
|
||||
{
|
||||
state.PopPack();
|
||||
return;
|
||||
}
|
||||
|
||||
Match define = defineRegex.Match(line);
|
||||
if (define.Success)
|
||||
{
|
||||
string key = define.Groups[1].Value;
|
||||
string value = define.Groups[2].Value.Trim();
|
||||
|
||||
if (defines.ContainsKey(key))
|
||||
defines[key] = value;
|
||||
else
|
||||
defines.Add(key, value);
|
||||
return;
|
||||
}
|
||||
|
||||
Match undef = undefRegex.Match(line);
|
||||
if (undef.Success)
|
||||
{
|
||||
var key = undef.Groups[1].Value;
|
||||
|
||||
if(defines.ContainsKey(key))
|
||||
defines.Remove(key);
|
||||
return;
|
||||
}
|
||||
|
||||
Match include = includeRegex.Match(line);
|
||||
if (include.Success)
|
||||
{
|
||||
string filename = include.Groups[1].Success ? include.Groups[1].Value : include.Groups[2].Value;
|
||||
|
||||
streamFileSystem.IncludeFile(filename);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private string Preprocess(string line)
|
||||
{
|
||||
bool defineMatched;
|
||||
line = commentProcessor.RemoveComments(line);
|
||||
|
||||
if (line.StartsWith("#"))
|
||||
{
|
||||
ParseCompilerExpression(line);
|
||||
return "";
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
defineMatched = false;
|
||||
foreach (KeyValuePair<string, string> define in defines)
|
||||
{
|
||||
Match match = Regex.Match(line, $@"^(.*\W)?{define.Key}(\W.*)?$");
|
||||
|
||||
if (!match.Success) continue;
|
||||
|
||||
line = match.Groups[1].Value + define.Value + match.Groups[2].Value;
|
||||
defineMatched = true;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (defineMatched);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
public string ReadLine()
|
||||
{
|
||||
return Preprocess(streamFileSystem.ReadLine());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
streamFileSystem.Close();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.PostProcessor
|
||||
{
|
||||
class PostProcessorUsages : IDataPostProcessor
|
||||
{
|
||||
public bool PostProcess(IDataRepository repository)
|
||||
{
|
||||
foreach (var dataTypeWithMembers in repository.GetAllStructs()
|
||||
.AsEnumerable<DataTypeWithMembers>()
|
||||
.Concat(repository.GetAllUnions()))
|
||||
{
|
||||
var information = repository.GetInformationFor(dataTypeWithMembers);
|
||||
|
||||
foreach (var memberInformation in information.OrderedMembers)
|
||||
{
|
||||
if (memberInformation.StructureType == null) continue;
|
||||
|
||||
memberInformation.StructureType.Usages.Add(information);
|
||||
|
||||
if (IsNonEmbeddedReference(memberInformation.Member))
|
||||
memberInformation.StructureType.NonEmbeddedReferenceExists = true;
|
||||
|
||||
if (IsPointerReference(memberInformation.Member))
|
||||
memberInformation.StructureType.PointerReferenceExists = true;
|
||||
|
||||
if (IsArrayReference(memberInformation.Member))
|
||||
memberInformation.StructureType.PointerReferenceExists = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsNonEmbeddedReference(Variable var)
|
||||
{
|
||||
return var.VariableType.References.Any();
|
||||
}
|
||||
|
||||
private static bool IsPointerReference(Variable var)
|
||||
{
|
||||
return var.VariableType.References.Any()
|
||||
&& var.VariableType.References.Last() is ReferenceTypePointer;
|
||||
}
|
||||
|
||||
private static bool IsArrayReference(Variable var)
|
||||
{
|
||||
return var.VariableType.References.Any()
|
||||
&& var.VariableType.References.Last() is ReferenceTypeArray;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
|
||||
{
|
||||
class TestCloseBlock : AbstractTokenTest<IHeaderParserState>
|
||||
{
|
||||
private const string NameToken = "close_with_name";
|
||||
private const string SemicolonToken = "close_with_semi_colon";
|
||||
|
||||
private readonly bool semicolonRequired;
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherLiteral("}"),
|
||||
new MatcherGroupOptional( new MatcherGroupAnd(
|
||||
new MatcherGroupOptional(new MatcherName().WithName(NameToken)),
|
||||
new MatcherLiteral(";").WithName(SemicolonToken)
|
||||
))
|
||||
};
|
||||
|
||||
public TestCloseBlock(bool semicolonRequired = false) : base(matchers)
|
||||
{
|
||||
this.semicolonRequired = semicolonRequired;
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(IHeaderParserState state)
|
||||
{
|
||||
if (HasMatcherTokens(NameToken))
|
||||
{
|
||||
if (state.CurrentBlock is INameAssignable nameAssignableBlock)
|
||||
{
|
||||
nameAssignableBlock.AssignName(GetMatcherTokens(NameToken)[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new TestFailedException($"Cannot give block '{state.CurrentBlock.Type}' a name when closing");
|
||||
}
|
||||
}
|
||||
|
||||
if (!HasMatcherTokens(SemicolonToken) && semicolonRequired)
|
||||
throw new TestFailedException($"Block '{state.CurrentBlock.Type}' needs to be closed with a '{'}'};'");
|
||||
|
||||
state.PopBlock();
|
||||
}
|
||||
}
|
||||
}
|
57
src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnum.cs
Normal file
57
src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnum.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
using ZoneCodeGenerator.Utils;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
|
||||
{
|
||||
class TestEnum : AbstractTokenTest<IHeaderParserState>
|
||||
{
|
||||
private const string TypedefToken = "typedef";
|
||||
private const string NameToken = "name";
|
||||
private const string TypenameToken = "typename";
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherGroupOptional(new MatcherLiteral("typedef").WithName(TypedefToken)),
|
||||
new MatcherLiteral("enum"),
|
||||
new MatcherGroupOptional(new MatcherName().WithName(NameToken)),
|
||||
new MatcherGroupOptional(new MatcherGroupAnd(new MatcherLiteral(":"), new MatcherTypename().WithName(TypenameToken))),
|
||||
new MatcherLiteral("{")
|
||||
};
|
||||
|
||||
public TestEnum() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(IHeaderParserState state)
|
||||
{
|
||||
var isTypedef = HasMatcherTokens(TypedefToken);
|
||||
var name = HasMatcherTokens(NameToken) ? GetMatcherTokens(NameToken)[0] : RandomName.GenerateName();
|
||||
var parentType = DataTypeBaseType.INT;
|
||||
|
||||
if (HasMatcherTokens(TypenameToken))
|
||||
{
|
||||
var typeName = GetMatcherTokens(TypenameToken)[0];
|
||||
var type = state.FindType(typeName);
|
||||
|
||||
if (type == null)
|
||||
throw new TestFailedException($"Parent type '{typeName}' of enum '{name}' not found.");
|
||||
|
||||
while (type is DataTypeTypedef typedef)
|
||||
{
|
||||
if (typedef.TypeDefinition.References.Count > 0)
|
||||
throw new TestFailedException($"Parent type of enum '{name}' cannot be a typedef that is an array or a pointer.");
|
||||
|
||||
type = typedef.TypeDefinition.Type;
|
||||
}
|
||||
|
||||
parentType = type as DataTypeBaseType ?? throw new TestFailedException($"Parent type of enum '{name}' must be a base type.");
|
||||
}
|
||||
|
||||
state.PushBlock(new BlockEnum(state, name, parentType, isTypedef));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
|
||||
{
|
||||
class TestEnumMember : AbstractTokenTest<IHeaderParserState>
|
||||
{
|
||||
private const string NameToken = "name";
|
||||
private const string NumberValueToken = "value_number";
|
||||
private const string EnumMemberValueToken = "value_string";
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherName().WithName(NameToken),
|
||||
new MatcherGroupOptional(new MatcherGroupAnd(
|
||||
new MatcherLiteral("="),
|
||||
new MatcherGroupOr(
|
||||
new MatcherNumber().WithName(NumberValueToken),
|
||||
new MatcherName().WithName(EnumMemberValueToken)
|
||||
))),
|
||||
new MatcherGroupOr(
|
||||
new MatcherLiteral(","),
|
||||
new MatcherLiteral("}").NonConsuming()
|
||||
)
|
||||
};
|
||||
|
||||
public TestEnumMember() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(IHeaderParserState state)
|
||||
{
|
||||
var name = GetMatcherTokens(NameToken)[0];
|
||||
long value;
|
||||
|
||||
if (!(state.CurrentBlock is BlockEnum _enum))
|
||||
throw new Exception("Excepted enum to be top block when parsing an enum member.");
|
||||
|
||||
if (HasMatcherTokens(NumberValueToken))
|
||||
{
|
||||
value = long.Parse(GetMatcherTokens(NumberValueToken)[0]);
|
||||
}
|
||||
else if(HasMatcherTokens(EnumMemberValueToken))
|
||||
{
|
||||
var stringValue = GetMatcherTokens(EnumMemberValueToken)[0];
|
||||
var memberWithFittingName = state.FindEnumMember(stringValue);
|
||||
|
||||
if(memberWithFittingName == null)
|
||||
throw new TestFailedException($"Could not find value for '{stringValue}'.");
|
||||
|
||||
value = memberWithFittingName.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = _enum.GetNextEnumValue();
|
||||
}
|
||||
|
||||
var enumMember = new EnumMember(name, value);
|
||||
_enum.AddMember(enumMember);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
|
||||
{
|
||||
class TestForwardDecl : AbstractTokenTest<IHeaderParserState>
|
||||
{
|
||||
private const string EnumToken = "enum";
|
||||
private const string StructToken = "struct";
|
||||
private const string UnionToken = "union";
|
||||
private const string NameToken = "name";
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherGroupOr(
|
||||
new MatcherLiteral("enum").WithName(EnumToken),
|
||||
new MatcherLiteral("struct").WithName(StructToken),
|
||||
new MatcherLiteral("union").WithName(UnionToken)
|
||||
),
|
||||
new MatcherName().WithName(NameToken),
|
||||
new MatcherLiteral(";")
|
||||
};
|
||||
|
||||
public TestForwardDecl() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(IHeaderParserState state)
|
||||
{
|
||||
var name = GetMatcherTokens(NameToken)[0];
|
||||
var _namespace = state.CurrentNamespace.ToString();
|
||||
|
||||
if (HasMatcherTokens(EnumToken))
|
||||
{
|
||||
state.AddForwardDeclaration(new ForwardDeclaration(_namespace, name, DataTypeType.Enum));
|
||||
}
|
||||
else if (HasMatcherTokens(StructToken))
|
||||
{
|
||||
state.AddForwardDeclaration(new ForwardDeclaration(_namespace, name, DataTypeType.Struct));
|
||||
}
|
||||
else if (HasMatcherTokens(UnionToken))
|
||||
{
|
||||
state.AddForwardDeclaration(new ForwardDeclaration(_namespace, name, DataTypeType.Union));
|
||||
}
|
||||
else
|
||||
throw new Exception("Unknown type for forward declaration.");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
|
||||
{
|
||||
class TestNamespace : AbstractTokenTest<IHeaderParserState>
|
||||
{
|
||||
private const string NamespaceNameToken = "namespace_name";
|
||||
|
||||
private static readonly TokenMatcher[] matchers =
|
||||
{
|
||||
new MatcherLiteral("namespace"),
|
||||
new MatcherName().WithName(NamespaceNameToken),
|
||||
new MatcherLiteral("{")
|
||||
};
|
||||
|
||||
public TestNamespace() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(IHeaderParserState state)
|
||||
{
|
||||
state.PushBlock(new BlockNamespace(state, GetMatcherTokens(NamespaceNameToken)[0]));
|
||||
}
|
||||
}
|
||||
}
|
69
src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestStruct.cs
Normal file
69
src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestStruct.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
using ZoneCodeGenerator.Utils;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
|
||||
{
|
||||
class TestStruct : AbstractTokenTest<IHeaderParserState>
|
||||
{
|
||||
private const string TypedefToken = "typedef";
|
||||
private const string NameToken = "name";
|
||||
private const string AlignToken = "align";
|
||||
private const string ParentToken = "parent";
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherGroupOptional(new MatcherLiteral("typedef").WithName(TypedefToken)),
|
||||
new MatcherGroupOptional(new MatcherLiteral("const")),
|
||||
new MatcherLiteral("struct"),
|
||||
new MatcherGroupOptional(new MatcherGroupAnd(
|
||||
new MatcherLiteral("__declspec"),
|
||||
new MatcherLiteral("("),
|
||||
new MatcherLiteral("align"),
|
||||
new MatcherLiteral("("),
|
||||
new MatcherNumber().WithName(AlignToken),
|
||||
new MatcherLiteral(")"),
|
||||
new MatcherLiteral(")")
|
||||
)),
|
||||
new MatcherGroupOptional(new MatcherName().WithName(NameToken)),
|
||||
new MatcherGroupOptional(new MatcherGroupAnd(
|
||||
new MatcherLiteral(":"),
|
||||
new MatcherTypename().WithName(ParentToken)
|
||||
)),
|
||||
new MatcherLiteral("{")
|
||||
};
|
||||
|
||||
public TestStruct() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(IHeaderParserState state)
|
||||
{
|
||||
var isTypedef = HasMatcherTokens(TypedefToken);
|
||||
var name = HasMatcherTokens(NameToken) ? GetMatcherTokens(NameToken)[0] : RandomName.GenerateName();
|
||||
|
||||
var block = new BlockStruct(state, name, isTypedef);
|
||||
|
||||
if (HasMatcherTokens(AlignToken))
|
||||
block.CustomAlignment = int.Parse(GetMatcherTokens(AlignToken)[0]);
|
||||
|
||||
if (HasMatcherTokens(ParentToken))
|
||||
{
|
||||
var parentDataTypeName = GetMatcherTokens(ParentToken)[0];
|
||||
var parentDataType = state.FindType(parentDataTypeName);
|
||||
|
||||
if(parentDataType == null)
|
||||
throw new TestFailedException($"Could not find parent data type '{parentDataTypeName}' for struct '{name}'");
|
||||
if(!(parentDataType is DataTypeStruct parentStruct))
|
||||
throw new TestFailedException($"Parent data type '{parentDataTypeName}' for struct '{name}' must be a struct as well.");
|
||||
|
||||
block.Inherit(parentStruct);
|
||||
}
|
||||
|
||||
state.PushBlock(block);
|
||||
}
|
||||
}
|
||||
}
|
96
src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs
Normal file
96
src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using System.Collections.Generic;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
|
||||
{
|
||||
class TestTypedef : AbstractTokenTest<IHeaderParserState>
|
||||
{
|
||||
private const string PointerToArrayVariant = "pointertoarray";
|
||||
private const string ArrayOfPointersVariant = "arrayofpointers";
|
||||
private const string TypeNameTokens = "typename";
|
||||
private const string PointerTokens = "pointer";
|
||||
private const string NameToken = "name";
|
||||
private const string ArrayTokens = "array";
|
||||
|
||||
private static readonly TokenMatcher[] arrayOfPointersMatchers = {
|
||||
new MatcherLiteral("typedef"),
|
||||
new MatcherTypename().WithName(TypeNameTokens),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
|
||||
new MatcherName().WithName(NameToken),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray().WithName(ArrayTokens)),
|
||||
new MatcherLiteral(";").WithName(ArrayOfPointersVariant)
|
||||
};
|
||||
|
||||
private static readonly TokenMatcher[] pointerToArrayMatchers = {
|
||||
new MatcherLiteral("typedef"),
|
||||
new MatcherTypename().WithName(TypeNameTokens),
|
||||
new MatcherLiteral("("),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
|
||||
new MatcherName().WithName(NameToken),
|
||||
new MatcherLiteral(")"),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherArray().WithName(ArrayTokens)),
|
||||
new MatcherLiteral(";").WithName(PointerToArrayVariant)
|
||||
};
|
||||
|
||||
private static readonly TokenMatcher[] matchers =
|
||||
{
|
||||
new MatcherGroupOr(
|
||||
new MatcherGroupAnd(arrayOfPointersMatchers),
|
||||
new MatcherGroupAnd(pointerToArrayMatchers)
|
||||
)
|
||||
};
|
||||
|
||||
public TestTypedef() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(IHeaderParserState state)
|
||||
{
|
||||
var name = GetMatcherTokens(NameToken)[0];
|
||||
var pointerDepth = GetMatcherTokens(PointerTokens).Count;
|
||||
|
||||
var typeName = string.Join(" ", GetMatcherTokens(TypeNameTokens));
|
||||
var type = state.FindType(typeName);
|
||||
|
||||
if (type == null)
|
||||
throw new TestFailedException($"Could not find type '{typeName}' of typedef '{name}'.");
|
||||
|
||||
var arrayTokens = GetMatcherTokens(ArrayTokens);
|
||||
var arraySize = new int[arrayTokens.Count];
|
||||
|
||||
for(var i = 0; i < arrayTokens.Count; i++)
|
||||
{
|
||||
if (!int.TryParse(arrayTokens[i], out arraySize[i]))
|
||||
throw new TestFailedException($"Array size '{arrayTokens[i]}' is not numeric.");
|
||||
}
|
||||
|
||||
var references = new List<ReferenceType>();
|
||||
|
||||
if (HasMatcherTokens(PointerToArrayVariant))
|
||||
{
|
||||
for (var i = 0; i < pointerDepth; i++)
|
||||
references.Add(new ReferenceTypePointer());
|
||||
|
||||
foreach(var array in arraySize)
|
||||
references.Add(new ReferenceTypeArray(array));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach(var array in arraySize)
|
||||
references.Add(new ReferenceTypeArray(array));
|
||||
|
||||
for (var i = 0; i < pointerDepth; i++)
|
||||
references.Add(new ReferenceTypePointer());
|
||||
}
|
||||
|
||||
var typeDeclaration = new TypeDeclaration(type, references);
|
||||
var typedef = new DataTypeTypedef(state.CurrentNamespace.ToString(), name, typeDeclaration);
|
||||
|
||||
state.AddDataType(typedef);
|
||||
}
|
||||
}
|
||||
}
|
69
src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestUnion.cs
Normal file
69
src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestUnion.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
using ZoneCodeGenerator.Utils;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
|
||||
{
|
||||
class TestUnion : AbstractTokenTest<IHeaderParserState>
|
||||
{
|
||||
private const string TypedefToken = "typedef";
|
||||
private const string NameToken = "name";
|
||||
private const string AlignToken = "align";
|
||||
private const string ParentToken = "parent";
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherGroupOptional(new MatcherLiteral("typedef").WithName(TypedefToken)),
|
||||
new MatcherGroupOptional(new MatcherLiteral("const")),
|
||||
new MatcherLiteral("union"),
|
||||
new MatcherGroupOptional(new MatcherGroupAnd(
|
||||
new MatcherLiteral("__declspec"),
|
||||
new MatcherLiteral("("),
|
||||
new MatcherLiteral("align"),
|
||||
new MatcherLiteral("("),
|
||||
new MatcherNumber().WithName(AlignToken),
|
||||
new MatcherLiteral(")"),
|
||||
new MatcherLiteral(")")
|
||||
)),
|
||||
new MatcherGroupOptional(new MatcherName().WithName(NameToken)),
|
||||
new MatcherGroupOptional(new MatcherGroupAnd(
|
||||
new MatcherLiteral(":"),
|
||||
new MatcherTypename().WithName(ParentToken)
|
||||
)),
|
||||
new MatcherLiteral("{")
|
||||
};
|
||||
|
||||
public TestUnion() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(IHeaderParserState state)
|
||||
{
|
||||
var isTypedef = HasMatcherTokens(TypedefToken);
|
||||
var name = HasMatcherTokens(NameToken) ? GetMatcherTokens(NameToken)[0] : RandomName.GenerateName();
|
||||
|
||||
var block = new BlockUnion(state, name, isTypedef);
|
||||
|
||||
if (HasMatcherTokens(AlignToken))
|
||||
block.CustomAlignment = int.Parse(GetMatcherTokens(AlignToken)[0]);
|
||||
|
||||
if (HasMatcherTokens(ParentToken))
|
||||
{
|
||||
var parentDataTypeName = GetMatcherTokens(ParentToken)[0];
|
||||
var parentDataType = state.FindType(parentDataTypeName);
|
||||
|
||||
if(parentDataType == null)
|
||||
throw new TestFailedException($"Could not find parent data type '{parentDataTypeName}' for union '{name}'");
|
||||
if(!(parentDataType is DataTypeUnion parentUnion))
|
||||
throw new TestFailedException($"Parent data type '{parentDataTypeName}' for union '{name}' must be a union as well.");
|
||||
|
||||
block.Inherit(parentUnion);
|
||||
}
|
||||
|
||||
state.PushBlock(block);
|
||||
}
|
||||
}
|
||||
}
|
112
src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs
Normal file
112
src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs
Normal file
@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
|
||||
{
|
||||
class TestVariable : AbstractTokenTest<IHeaderParserState>
|
||||
{
|
||||
private const string PointerToArrayVariant = "pointertoarray";
|
||||
private const string ArrayOfPointersVariant = "arrayofpointers";
|
||||
private const string TypeNameToken = "typename";
|
||||
private const string PointerTokens = "pointer";
|
||||
private const string NameToken = "name";
|
||||
private const string ArrayTokens = "array";
|
||||
private const string BitSizeToken = "bitsize";
|
||||
|
||||
private static readonly TokenMatcher[] arrayOfPointersMatchers = {
|
||||
new MatcherTypename().WithName(TypeNameToken),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
|
||||
new MatcherName().WithName(NameToken),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray().WithName(ArrayTokens)),
|
||||
new MatcherGroupOptional(new MatcherGroupAnd(
|
||||
new MatcherLiteral(":"),
|
||||
new MatcherNumber().WithName(BitSizeToken)
|
||||
)),
|
||||
new MatcherLiteral(";").WithName(ArrayOfPointersVariant)
|
||||
};
|
||||
|
||||
private static readonly TokenMatcher[] pointerToArrayMatchers = {
|
||||
new MatcherTypename().WithName(TypeNameToken),
|
||||
new MatcherLiteral("("),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
|
||||
new MatcherName().WithName(NameToken),
|
||||
new MatcherLiteral(")"),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherArray().WithName(ArrayTokens)),
|
||||
new MatcherLiteral(";").WithName(PointerToArrayVariant)
|
||||
};
|
||||
|
||||
private static readonly TokenMatcher[] matchers =
|
||||
{
|
||||
new MatcherGroupOr(
|
||||
new MatcherGroupAnd(arrayOfPointersMatchers),
|
||||
new MatcherGroupAnd(pointerToArrayMatchers)
|
||||
)
|
||||
};
|
||||
|
||||
public TestVariable() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(IHeaderParserState state)
|
||||
{
|
||||
var name = GetMatcherTokens(NameToken)[0];
|
||||
var typeName = GetMatcherTokens(TypeNameToken)[0];
|
||||
var type = state.FindType(typeName);
|
||||
|
||||
if (type == null)
|
||||
throw new TestFailedException($"Type '{typeName}' not found.");
|
||||
|
||||
var pointerDepth = GetMatcherTokens(PointerTokens).Count;
|
||||
|
||||
var arrayTokens = GetMatcherTokens(ArrayTokens);
|
||||
var arraySize = new int[arrayTokens.Count];
|
||||
|
||||
int? bitSize = null;
|
||||
if (HasMatcherTokens(BitSizeToken))
|
||||
bitSize = int.Parse(GetMatcherTokens(BitSizeToken)[0]);
|
||||
|
||||
for(var i = 0; i < arrayTokens.Count; i++)
|
||||
{
|
||||
if (!int.TryParse(arrayTokens[i], out arraySize[i]))
|
||||
throw new TestFailedException($"Array size '{arrayTokens[i]}' is not numeric.");
|
||||
}
|
||||
|
||||
if (state.CurrentBlock is IVariableHolder variableHolder)
|
||||
{
|
||||
var references = new List<ReferenceType>();
|
||||
|
||||
if (HasMatcherTokens(PointerToArrayVariant))
|
||||
{
|
||||
for (var i = 0; i < pointerDepth; i++)
|
||||
references.Add(new ReferenceTypePointer());
|
||||
foreach(var array in arraySize)
|
||||
references.Add(new ReferenceTypeArray(array));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach(var array in arraySize)
|
||||
references.Add(new ReferenceTypeArray(array));
|
||||
|
||||
for (var i = 0; i < pointerDepth; i++)
|
||||
references.Add(new ReferenceTypePointer());
|
||||
}
|
||||
|
||||
var typeDeclaration = bitSize == null ? new TypeDeclaration(type, references) : new TypeDeclaration(type, bitSize.Value, references);
|
||||
|
||||
var variable = new Variable(name, typeDeclaration);
|
||||
|
||||
variableHolder.AddVariable(variable);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Expected current block to be a variable holder when parsing variables.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using ZoneCodeGenerator.Interface;
|
||||
using ZoneCodeGenerator.Parsing.CommandFile.Impl;
|
||||
using ZoneCodeGenerator.Parsing.CommandFile.PostProcessor;
|
||||
using ZoneCodeGenerator.Parsing.Impl;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile
|
||||
{
|
||||
static class CommandFileReader
|
||||
{
|
||||
private static readonly IDataPostProcessor[] postProcessors =
|
||||
{
|
||||
new PostProcessorDefaultBlock(),
|
||||
};
|
||||
|
||||
public static bool ReadFile(string path, CUISession session)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (IIncludingParsingStream streamFileSystem = new IncludingStreamFileSystem(path))
|
||||
{
|
||||
var state = new CommandParserState(session.Repository);
|
||||
|
||||
using (IParsingFileStream preprocessorStream = new CommandFilePreprocessor(streamFileSystem))
|
||||
{
|
||||
var lexer = new Lexer(preprocessorStream);
|
||||
var parser = new Parser<ICommandParserState>(state, lexer);
|
||||
|
||||
if (!parser.Parse())
|
||||
return false;
|
||||
|
||||
preprocessorStream.Close();
|
||||
streamFileSystem.Close();
|
||||
|
||||
if (!state.Apply(session))
|
||||
{
|
||||
Console.WriteLine("Finalizing from command file failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PostProcessRepository(session.Repository))
|
||||
{
|
||||
Console.WriteLine("Postprocessing commands failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool PostProcessRepository(IDataRepository repository)
|
||||
{
|
||||
return postProcessors.All(postProcessor => postProcessor.PostProcess(repository));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Domain.FastFileStructure;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile
|
||||
{
|
||||
interface ICommandParserState : IParserState<ICommandParserState>
|
||||
{
|
||||
string Game { get; set; }
|
||||
IReadOnlyDataRepository Repository { get; }
|
||||
List<FastFileBlock> FastFileBlocks { get; }
|
||||
DataTypeWithMembers DataTypeInUse { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using ZoneCodeGenerator.Parsing.Impl;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.Impl
|
||||
{
|
||||
class CommandFilePreprocessor : IParsingFileStream
|
||||
{
|
||||
private static readonly Regex includeRegex = new Regex(@"^\s*include\s*(?:\""(.*)\""|\<(.*)\>)\s*$");
|
||||
|
||||
private readonly IIncludingParsingStream parsingStream;
|
||||
private readonly ICommentProcessor commentProcessor;
|
||||
|
||||
public CommandFilePreprocessor(IIncludingParsingStream parsingStream)
|
||||
{
|
||||
this.parsingStream = parsingStream;
|
||||
commentProcessor = new CommentProcessor();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
parsingStream.Close();
|
||||
}
|
||||
|
||||
public bool EndOfStream => parsingStream.EndOfStream;
|
||||
public string Filename => parsingStream.Filename;
|
||||
public int Line => parsingStream.Line;
|
||||
|
||||
public string ReadLine()
|
||||
{
|
||||
return Preprocess(parsingStream.ReadLine());
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
parsingStream.Close();
|
||||
}
|
||||
|
||||
private string Preprocess(string line)
|
||||
{
|
||||
line = commentProcessor.RemoveComments(line);
|
||||
|
||||
var includeMatch = includeRegex.Match(line);
|
||||
|
||||
if (includeMatch.Success)
|
||||
{
|
||||
var filename = includeMatch.Groups[1].Success ? includeMatch.Groups[1].Value : includeMatch.Groups[2].Value;
|
||||
|
||||
parsingStream.IncludeFile(filename);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Domain.FastFileStructure;
|
||||
using ZoneCodeGenerator.Interface;
|
||||
using ZoneCodeGenerator.Parsing.CommandFile.Tests;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.Impl
|
||||
{
|
||||
class CommandParserState : ICommandParserState
|
||||
{
|
||||
private static readonly ITokenTest<ICommandParserState>[] tests = {
|
||||
new TestAsset(),
|
||||
new TestBlock(),
|
||||
new TestCondition(),
|
||||
new TestCount(),
|
||||
new TestGame(),
|
||||
new TestReorder(),
|
||||
new TestScriptString(),
|
||||
new TestUse()
|
||||
};
|
||||
|
||||
public string Game { get; set; }
|
||||
public IReadOnlyDataRepository Repository { get; }
|
||||
public List<FastFileBlock> FastFileBlocks { get; }
|
||||
public DataTypeWithMembers DataTypeInUse { get; set; }
|
||||
|
||||
public CommandParserState(IReadOnlyDataRepository repository)
|
||||
{
|
||||
Repository = repository;
|
||||
FastFileBlocks = new List<FastFileBlock>();
|
||||
DataTypeInUse = null;
|
||||
}
|
||||
|
||||
public IEnumerable<ITokenTest<ICommandParserState>> GetTests()
|
||||
{
|
||||
return tests;
|
||||
}
|
||||
|
||||
public bool Apply(CUISession session)
|
||||
{
|
||||
session.Game = Game;
|
||||
|
||||
foreach (var block in FastFileBlocks)
|
||||
{
|
||||
session.Repository.Add(block);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
using System.Linq;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Domain.FastFileStructure;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
|
||||
{
|
||||
class PostProcessorDefaultBlock : IDataPostProcessor
|
||||
{
|
||||
public bool PostProcess(IDataRepository repository)
|
||||
{
|
||||
var memberDataTypes =
|
||||
repository.GetAllStructs()
|
||||
.AsEnumerable<DataTypeWithMembers>()
|
||||
.Concat(repository.GetAllUnions());
|
||||
|
||||
var defaultTemp = repository.GetAllFastFileBlocks().First(block => block.BlockType == FastFileBlock.Type.Temp && block.IsDefault) ??
|
||||
repository.GetAllFastFileBlocks().First(block => block.BlockType == FastFileBlock.Type.Temp);
|
||||
|
||||
var defaultNormal = repository.GetAllFastFileBlocks().First(block => block.BlockType == FastFileBlock.Type.Normal && block.IsDefault) ??
|
||||
repository.GetAllFastFileBlocks().First(block => block.BlockType == FastFileBlock.Type.Normal);
|
||||
|
||||
foreach (var memberType in memberDataTypes)
|
||||
{
|
||||
var info = repository.GetInformationFor(memberType);
|
||||
|
||||
info.Block = info.IsAsset ? defaultTemp : defaultNormal;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
59
src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestAsset.cs
Normal file
59
src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestAsset.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
||||
{
|
||||
class TestAsset : AbstractTokenTest<ICommandParserState>
|
||||
{
|
||||
private const string AssetTypeNameToken = "name";
|
||||
private const string AssetEnumEntryToken = "enumEntry";
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherLiteral("asset"),
|
||||
new MatcherTypename().WithName(AssetTypeNameToken),
|
||||
new MatcherName().WithName(AssetEnumEntryToken),
|
||||
new MatcherLiteral(";")
|
||||
};
|
||||
|
||||
public TestAsset() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(ICommandParserState state)
|
||||
{
|
||||
var assetTypeName = GetMatcherTokens(AssetTypeNameToken)[0];
|
||||
|
||||
var assetType = state.Repository.GetDataTypeByName(assetTypeName);
|
||||
if (assetType == null)
|
||||
{
|
||||
throw new LoadingException($"Could not find type '{assetTypeName}' to mark it as an asset.");
|
||||
}
|
||||
|
||||
if (!(assetType is DataTypeWithMembers assetTypeWithMembers))
|
||||
{
|
||||
throw new LoadingException($"Type of asset '{assetTypeName}' needs to be struct or union.");
|
||||
}
|
||||
|
||||
var assetInfo = state.Repository.GetInformationFor(assetTypeWithMembers);
|
||||
if (assetType == null)
|
||||
{
|
||||
throw new LoadingException($"Could not find information for type '{assetTypeName}' to mark it as an asset.");
|
||||
}
|
||||
|
||||
var enumEntryName = GetMatcherTokens(AssetEnumEntryToken)[0];
|
||||
var enumEntry = state.Repository.GetAllEnums()
|
||||
.SelectMany(_enum => _enum.Members)
|
||||
.FirstOrDefault(member => member.Name.Equals(enumEntryName, StringComparison.CurrentCultureIgnoreCase));
|
||||
|
||||
assetInfo.AssetEnumEntry = enumEntry ?? throw new LoadingException(
|
||||
$"Could not find enum entry '{enumEntryName}' as an asset type index for asset type '{assetTypeName}'.");
|
||||
}
|
||||
}
|
||||
}
|
52
src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestBlock.cs
Normal file
52
src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestBlock.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using ZoneCodeGenerator.Domain.FastFileStructure;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
||||
{
|
||||
class TestBlock : AbstractTokenTest<ICommandParserState>
|
||||
{
|
||||
private const string BlockNumberToken = "num";
|
||||
private const string BlockTypeToken = "type";
|
||||
private const string BlockNameToken = "name";
|
||||
private const string DefaultToken = "default";
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherLiteral("block"),
|
||||
new MatcherNumber().WithName(BlockNumberToken),
|
||||
new MatcherName().WithName(BlockTypeToken),
|
||||
new MatcherName().WithName(BlockNameToken),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple,new MatcherGroupOr(
|
||||
new MatcherLiteral("default").WithName(DefaultToken)
|
||||
)),
|
||||
new MatcherLiteral(";")
|
||||
};
|
||||
|
||||
public TestBlock() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(ICommandParserState state)
|
||||
{
|
||||
var blockName = GetMatcherTokens(BlockNameToken)[0];
|
||||
var blockNumber = int.Parse(GetMatcherTokens(BlockNumberToken)[0]);
|
||||
|
||||
var blockTypeInput = GetMatcherTokens(BlockTypeToken)[0];
|
||||
if (!Enum.TryParse(blockTypeInput, true, out FastFileBlock.Type blockType))
|
||||
{
|
||||
var blockTypeValues = Enum.GetValues(typeof(FastFileBlock.Type)).OfType<FastFileBlock.Type>()
|
||||
.Select(type => type.ToString());
|
||||
|
||||
throw new TestFailedException($"Unknown fastfile block type '{blockTypeInput}'. Must be one of the following: {string.Join(", ", blockTypeValues)}");
|
||||
}
|
||||
|
||||
var block = new FastFileBlock(blockName, blockNumber, blockType, HasMatcherTokens(DefaultToken));
|
||||
|
||||
state.FastFileBlocks.Add(block);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
||||
{
|
||||
class TestCondition : AbstractTokenTest<ICommandParserState>
|
||||
{
|
||||
private const string TypeNameToken = "typeName";
|
||||
private const string ConditionStatementTag = "conditionStatement";
|
||||
private const string ConditionChainTag = "conditionChain";
|
||||
private const string ConditionChainLinkTag = "conditionChainLink";
|
||||
private const string OperationTag = "operation";
|
||||
private const string OperandTag = "operand";
|
||||
|
||||
private static readonly TokenMatcher operand = new MatcherGroupOr(
|
||||
new MatcherGroupAnd(
|
||||
new MatcherTypename(),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray())
|
||||
),
|
||||
new MatcherNumber(),
|
||||
new MatcherLiteral("true"),
|
||||
new MatcherLiteral("false")
|
||||
).WithTag(OperandTag);
|
||||
|
||||
private static readonly TokenMatcher operation = new MatcherGroupOr(
|
||||
new MatcherLiteral("+"),
|
||||
new MatcherLiteral("-"),
|
||||
new MatcherLiteral("*"),
|
||||
new MatcherLiteral("/"),
|
||||
new MatcherGroupAnd(new MatcherLiteral("<"), new MatcherLiteral("<")),
|
||||
new MatcherGroupAnd(new MatcherLiteral(">"), new MatcherLiteral(">"))
|
||||
).WithTag(OperationTag);
|
||||
|
||||
private static readonly TokenMatcher conditionStatement = new MatcherGroupOr(
|
||||
new MatcherGroupAnd(
|
||||
new MatcherLiteral("("),
|
||||
new MatcherWithTag(ConditionStatementTag),
|
||||
new MatcherLiteral(")")
|
||||
),
|
||||
new MatcherGroupAnd(
|
||||
new MatcherWithTag(OperandTag),
|
||||
new MatcherGroupOptional(new MatcherGroupAnd(
|
||||
new MatcherWithTag(OperationTag),
|
||||
new MatcherWithTag(OperandTag)
|
||||
))
|
||||
)
|
||||
).WithTag(ConditionStatementTag);
|
||||
|
||||
private static readonly TokenMatcher conditionChainLink = new MatcherGroupOr(
|
||||
new MatcherGroupAnd(new MatcherLiteral("="), new MatcherLiteral("=")),
|
||||
new MatcherGroupAnd(new MatcherLiteral("!"), new MatcherLiteral("=")),
|
||||
new MatcherGroupAnd(new MatcherLiteral("<"), new MatcherLiteral("=")),
|
||||
new MatcherGroupAnd(new MatcherLiteral(">"), new MatcherLiteral("=")),
|
||||
new MatcherLiteral("<"),
|
||||
new MatcherLiteral(">")
|
||||
).WithTag(ConditionChainLinkTag);
|
||||
|
||||
private static readonly TokenMatcher conditionChain = new MatcherGroupAnd(
|
||||
new MatcherWithTag(ConditionStatementTag),
|
||||
new MatcherWithTag(ConditionChainLinkTag),
|
||||
new MatcherWithTag(ConditionStatementTag)
|
||||
).WithTag(ConditionChainTag);
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherLiteral("set"),
|
||||
new MatcherLiteral("condition"),
|
||||
new MatcherTypename().WithName(TypeNameToken),
|
||||
new MatcherGroupOr(
|
||||
new MatcherLiteral("never"),
|
||||
new MatcherWithTag(ConditionChainTag)
|
||||
),
|
||||
new MatcherLiteral(";")
|
||||
};
|
||||
|
||||
public TestCondition() : base(matchers)
|
||||
{
|
||||
AddTaggedMatcher(conditionChain);
|
||||
AddTaggedMatcher(conditionChainLink);
|
||||
AddTaggedMatcher(conditionStatement);
|
||||
AddTaggedMatcher(operation);
|
||||
AddTaggedMatcher(operand);
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(ICommandParserState state)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
87
src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs
Normal file
87
src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
||||
{
|
||||
class TestCount : AbstractTokenTest<ICommandParserState>
|
||||
{
|
||||
private const string TypeNameToken = "typeName";
|
||||
private const string ConditionStatementTag = "conditionStatement";
|
||||
private const string ConditionChainTag = "conditionChain";
|
||||
private const string ConditionChainLinkTag = "conditionChainLink";
|
||||
private const string OperationTag = "operation";
|
||||
private const string OperandTag = "operand";
|
||||
|
||||
private static readonly TokenMatcher operand = new MatcherGroupOr(
|
||||
new MatcherGroupAnd(
|
||||
new MatcherTypename(),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray())
|
||||
),
|
||||
new MatcherNumber()
|
||||
).WithTag(OperandTag);
|
||||
|
||||
private static readonly TokenMatcher operation = new MatcherGroupOr(
|
||||
new MatcherLiteral("+"),
|
||||
new MatcherLiteral("-"),
|
||||
new MatcherLiteral("*"),
|
||||
new MatcherLiteral("/"),
|
||||
new MatcherGroupAnd(new MatcherLiteral("<"), new MatcherLiteral("<")),
|
||||
new MatcherGroupAnd(new MatcherLiteral(">"), new MatcherLiteral(">"))
|
||||
).WithTag(OperationTag);
|
||||
|
||||
private static readonly TokenMatcher conditionStatement = new MatcherGroupOr(
|
||||
new MatcherGroupAnd(
|
||||
new MatcherLiteral("("),
|
||||
new MatcherWithTag(ConditionStatementTag),
|
||||
new MatcherLiteral(")")
|
||||
),
|
||||
new MatcherGroupAnd(
|
||||
new MatcherWithTag(OperandTag),
|
||||
new MatcherGroupOptional(new MatcherGroupAnd(
|
||||
new MatcherWithTag(OperationTag),
|
||||
new MatcherWithTag(OperandTag)
|
||||
))
|
||||
)
|
||||
).WithTag(ConditionStatementTag);
|
||||
|
||||
private static readonly TokenMatcher conditionChainLink = new MatcherGroupOr(
|
||||
new MatcherGroupAnd(new MatcherLiteral("|"), new MatcherLiteral("|")),
|
||||
new MatcherGroupAnd(new MatcherLiteral("&"), new MatcherLiteral("&"))
|
||||
).WithTag(ConditionChainLinkTag);
|
||||
|
||||
private static readonly TokenMatcher conditionChain = new MatcherGroupAnd(
|
||||
new MatcherWithTag(ConditionStatementTag),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherGroupAnd(
|
||||
new MatcherWithTag(ConditionChainLinkTag),
|
||||
new MatcherWithTag(ConditionStatementTag)
|
||||
))
|
||||
).WithTag(ConditionChainTag);
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherLiteral("set"),
|
||||
new MatcherLiteral("count"),
|
||||
new MatcherTypename().WithName(TypeNameToken),
|
||||
new MatcherWithTag(ConditionChainTag),
|
||||
new MatcherLiteral(";")
|
||||
};
|
||||
|
||||
public TestCount() : base(matchers)
|
||||
{
|
||||
AddTaggedMatcher(conditionStatement);
|
||||
AddTaggedMatcher(conditionChain);
|
||||
AddTaggedMatcher(conditionChainLink);
|
||||
AddTaggedMatcher(operation);
|
||||
AddTaggedMatcher(operand);
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(ICommandParserState state)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
37
src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestGame.cs
Normal file
37
src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestGame.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ZoneCodeGenerator.Domain.FastFileStructure;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
||||
{
|
||||
class TestGame : AbstractTokenTest<ICommandParserState>
|
||||
{
|
||||
private const string GameNameToken = "name";
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherLiteral("game"),
|
||||
new MatcherName().WithName(GameNameToken),
|
||||
new MatcherLiteral(";")
|
||||
};
|
||||
|
||||
public TestGame() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(ICommandParserState state)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(state.Game))
|
||||
{
|
||||
throw new TestFailedException($"Game has already been set with value '{state.Game}'");
|
||||
}
|
||||
|
||||
state.Game = GetMatcherTokens(GameNameToken)[0];
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
||||
{
|
||||
class TestReorder : AbstractTokenTest<ICommandParserState>
|
||||
{
|
||||
private const string TypeNameToken = "typeName";
|
||||
private const string ReorderMemberNameToken = "member";
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherLiteral("reorder"),
|
||||
new MatcherGroupOptional(new MatcherTypename().WithName(TypeNameToken)),
|
||||
new MatcherLiteral(":"),
|
||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherName().WithName(ReorderMemberNameToken)),
|
||||
new MatcherLiteral(";")
|
||||
};
|
||||
|
||||
public TestReorder() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(ICommandParserState state)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
||||
{
|
||||
class TestScriptString : AbstractTokenTest<ICommandParserState>
|
||||
{
|
||||
private const string MemberTypeNameToken = "name";
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherLiteral("set"),
|
||||
new MatcherLiteral("scriptstring"),
|
||||
new MatcherTypename().WithName(MemberTypeNameToken),
|
||||
new MatcherLiteral(";")
|
||||
};
|
||||
|
||||
public TestScriptString() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(ICommandParserState state)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
41
src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestUse.cs
Normal file
41
src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestUse.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Parsing.Matching;
|
||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
||||
{
|
||||
class TestUse : AbstractTokenTest<ICommandParserState>
|
||||
{
|
||||
private const string TypeNameToken = "typeName";
|
||||
|
||||
private static readonly TokenMatcher[] matchers = {
|
||||
new MatcherLiteral("use"),
|
||||
new MatcherTypename().WithName(TypeNameToken),
|
||||
new MatcherLiteral(";")
|
||||
};
|
||||
|
||||
public TestUse() : base(matchers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void ProcessMatch(ICommandParserState state)
|
||||
{
|
||||
var typeName = GetMatcherTokens(TypeNameToken)[0];
|
||||
var dataTypeToUse = state.Repository.GetDataTypeByName(typeName);
|
||||
|
||||
if (dataTypeToUse == null)
|
||||
{
|
||||
throw new LoadingException($"Could not find data type '{typeName}'");
|
||||
}
|
||||
|
||||
if (!(dataTypeToUse is DataTypeWithMembers dataTypeWithMembersToUse))
|
||||
{
|
||||
throw new LoadingException($"To use data type '{typeName}' it must either be a struct or a union.");
|
||||
}
|
||||
|
||||
state.DataTypeInUse = dataTypeWithMembersToUse;
|
||||
}
|
||||
}
|
||||
}
|
7
src/ZoneCodeGenerator/Parsing/ICommentProcessor.cs
Normal file
7
src/ZoneCodeGenerator/Parsing/ICommentProcessor.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace ZoneCodeGenerator.Parsing
|
||||
{
|
||||
interface ICommentProcessor
|
||||
{
|
||||
string RemoveComments(string line);
|
||||
}
|
||||
}
|
9
src/ZoneCodeGenerator/Parsing/IDataPostProcessor.cs
Normal file
9
src/ZoneCodeGenerator/Parsing/IDataPostProcessor.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing
|
||||
{
|
||||
interface IDataPostProcessor
|
||||
{
|
||||
bool PostProcess(IDataRepository repository);
|
||||
}
|
||||
}
|
12
src/ZoneCodeGenerator/Parsing/IIncludingParsingStream.cs
Normal file
12
src/ZoneCodeGenerator/Parsing/IIncludingParsingStream.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace ZoneCodeGenerator.Parsing
|
||||
{
|
||||
interface IIncludingParsingStream : IParsingFileStream
|
||||
{
|
||||
/// <summary>
|
||||
/// Pushes back current file and the position in it to read from another file now instead.
|
||||
/// After completion returns back to the previous file.
|
||||
/// </summary>
|
||||
/// <param name="filename"></param>
|
||||
void IncludeFile(string filename);
|
||||
}
|
||||
}
|
14
src/ZoneCodeGenerator/Parsing/ILexer.cs
Normal file
14
src/ZoneCodeGenerator/Parsing/ILexer.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace ZoneCodeGenerator.Parsing
|
||||
{
|
||||
interface ILexer
|
||||
{
|
||||
int CurrentLine { get; }
|
||||
string CurrentFile { get; }
|
||||
bool IsEndOfStream { get; }
|
||||
int CachedTokenCount { get; }
|
||||
|
||||
string NextToken();
|
||||
string PeekToken(int index = 0);
|
||||
void SkipTokens(int count);
|
||||
}
|
||||
}
|
10
src/ZoneCodeGenerator/Parsing/IParserState.cs
Normal file
10
src/ZoneCodeGenerator/Parsing/IParserState.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing
|
||||
{
|
||||
interface IParserState<in TState> where TState : IParserState<TState>
|
||||
{
|
||||
IEnumerable<ITokenTest<TState>> GetTests();
|
||||
}
|
||||
}
|
33
src/ZoneCodeGenerator/Parsing/IParsingFileStream.cs
Normal file
33
src/ZoneCodeGenerator/Parsing/IParsingFileStream.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing
|
||||
{
|
||||
interface IParsingFileStream : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether the end of the stream has been reached.
|
||||
/// </summary>
|
||||
bool EndOfStream { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The current filename.
|
||||
/// </summary>
|
||||
string Filename { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The current line in the current file.
|
||||
/// </summary>
|
||||
int Line { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Reads a line from the current header and returns it.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
string ReadLine();
|
||||
|
||||
/// <summary>
|
||||
/// Closes this and all underlying streams.
|
||||
/// </summary>
|
||||
void Close();
|
||||
}
|
||||
}
|
57
src/ZoneCodeGenerator/Parsing/Impl/CommentProcessor.cs
Normal file
57
src/ZoneCodeGenerator/Parsing/Impl/CommentProcessor.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.Impl
|
||||
{
|
||||
class CommentProcessor : ICommentProcessor
|
||||
{
|
||||
private const string LineCommentStart = "//";
|
||||
private const string BlockCommentStart = "/*";
|
||||
private const string BlockCommentEnd = "*/";
|
||||
|
||||
private bool inComment;
|
||||
|
||||
public CommentProcessor()
|
||||
{
|
||||
inComment = false;
|
||||
}
|
||||
|
||||
public string RemoveComments(string line)
|
||||
{
|
||||
if (inComment)
|
||||
{
|
||||
var idx = line.IndexOf(BlockCommentEnd, StringComparison.Ordinal);
|
||||
|
||||
if(idx == -1)
|
||||
return "";
|
||||
|
||||
line = line.Substring(idx + BlockCommentEnd.Length);
|
||||
inComment = false;
|
||||
}
|
||||
|
||||
var commentIndex = line.IndexOf(LineCommentStart, StringComparison.Ordinal);
|
||||
if (commentIndex != -1)
|
||||
line = line.Remove(commentIndex).Trim();
|
||||
|
||||
while (true)
|
||||
{
|
||||
var indexBlockCommentBegin = line.IndexOf(BlockCommentStart, StringComparison.Ordinal);
|
||||
|
||||
if (indexBlockCommentBegin == -1)
|
||||
break;
|
||||
|
||||
var indexBlockCommentEnd = line.IndexOf(BlockCommentEnd, indexBlockCommentBegin, StringComparison.Ordinal);
|
||||
|
||||
if(indexBlockCommentEnd == -1)
|
||||
{
|
||||
line = line.Remove(indexBlockCommentBegin).Trim();
|
||||
inComment = true;
|
||||
break;
|
||||
}
|
||||
|
||||
line = line.Remove(indexBlockCommentBegin, indexBlockCommentEnd + BlockCommentEnd.Length - indexBlockCommentBegin).Trim();
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user