Import code from previous AssetBuilder version

This commit is contained in:
Jan 2019-09-24 10:45:09 +02:00
parent 5609557516
commit 0d8432d4f7
919 changed files with 154412 additions and 26 deletions

7
.gitignore vendored
View File

@ -11,8 +11,13 @@
*.obj
*.log
*.bak
ipch/*
.vs/
local/
bin/
lib/
local/
obj/
packages/
TestResults/

View File

@ -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
View 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
View 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
View 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>

View 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;
};

View 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;
};

View 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;
};

View 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);
}

View 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;
};

View 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);
}

View 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;
};

View 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);
}

View 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;
};

View 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;
}
}
};

View File

@ -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
View 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>

View File

@ -0,0 +1,3 @@
#pragma once
#define STR(x) #x

145
src/Utils/Utils/FileAPI.cpp Normal file
View 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
View 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);
};

View 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>

View File

@ -0,0 +1,9 @@
namespace ZoneCodeGenerator.Domain
{
class DataException : LoadingException
{
public DataException(string message) : base(message)
{
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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);
}
}
}

View File

@ -0,0 +1,11 @@
namespace ZoneCodeGenerator.Domain
{
enum DataTypeType
{
Struct,
Union,
Enum,
Typedef,
BaseType
}
}

View 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;
}
}

View 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);
}
}
}

View 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();
}
}

View 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;
}
}
}

View File

@ -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;
}
}
}

View 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;
}
}

View 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}";
}
}
}

View File

@ -0,0 +1,7 @@
namespace ZoneCodeGenerator.Domain
{
abstract class ReferenceType
{
}
}

View File

@ -0,0 +1,12 @@
namespace ZoneCodeGenerator.Domain
{
class ReferenceTypeArray : ReferenceType
{
public int ArraySize { get; }
public ReferenceTypeArray(int arraySize)
{
ArraySize = arraySize;
}
}
}

View File

@ -0,0 +1,6 @@
namespace ZoneCodeGenerator.Domain
{
class ReferenceTypePointer : ReferenceType
{
}
}

View File

@ -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;
}
}
}

View File

@ -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>();
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}
}

View 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));
}
}
}
}

View 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;
}
}
}

View 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;
}
}

View File

@ -0,0 +1,2 @@
test() ::= <<
>>

View 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)$
>>

View 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
>>

View 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;
}
}
}

View File

@ -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;
}
}
}
}

View 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
}
}
}

View 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));
}
}
}

View 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 = ".";
}
}
}

View 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,
};
}
}

View 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();
}
}
}

View File

@ -0,0 +1,11 @@
using System;
namespace ZoneCodeGenerator
{
class LoadingException : Exception
{
public LoadingException(string message) : base(message)
{
}
}
}

View File

@ -0,0 +1,11 @@
namespace ZoneCodeGenerator.Parsing.C_Header
{
enum BlockType
{
None,
Enum,
Namespace,
Struct,
Union
}
}

View 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);
}
}

View 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);
}
}
}

View File

@ -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
}
}
}

View 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
}
}
}

View 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);
}
}
}

View 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);
}
}
}

View File

@ -0,0 +1,7 @@
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
{
interface INameAssignable
{
void AssignName(string nameAssignment);
}
}

View File

@ -0,0 +1,9 @@
using ZoneCodeGenerator.Domain;
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
{
interface IVariableBlock
{
Variable GetDefinedVariable();
}
}

View File

@ -0,0 +1,9 @@
using ZoneCodeGenerator.Domain;
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
{
interface IVariableHolder
{
void AddVariable(Variable variable);
}
}

View 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();
}
}
}

View 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);
}
}

View 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();
}
}
}

View 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();
}
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}
}

View 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));
}
}
}

View File

@ -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);
}
}
}

View File

@ -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.");
}
}
}

View File

@ -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]));
}
}
}

View 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);
}
}
}

View 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);
}
}
}

View 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);
}
}
}

View 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.");
}
}
}
}

View File

@ -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));
}
}
}

View File

@ -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; }
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View 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}'.");
}
}
}

View 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);
}
}
}

View File

@ -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)
{
}
}
}

View 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)
{
}
}
}

View 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];
}
}
}

View File

@ -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)
{
}
}
}

View File

@ -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)
{
}
}
}

View 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;
}
}
}

View File

@ -0,0 +1,7 @@
namespace ZoneCodeGenerator.Parsing
{
interface ICommentProcessor
{
string RemoveComments(string line);
}
}

View File

@ -0,0 +1,9 @@
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Parsing
{
interface IDataPostProcessor
{
bool PostProcess(IDataRepository repository);
}
}

View 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);
}
}

View 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);
}
}

View 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();
}
}

View 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();
}
}

View 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