Skip to content

Commit d119610

Browse files
committed
INI C++ SAX Parsing
1 parent bcb096d commit d119610

File tree

8 files changed

+511
-0
lines changed

8 files changed

+511
-0
lines changed

09_INIpp/09_INIpp.vcxproj

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<ItemGroup Label="ProjectConfigurations">
4+
<ProjectConfiguration Include="Debug|Win32">
5+
<Configuration>Debug</Configuration>
6+
<Platform>Win32</Platform>
7+
</ProjectConfiguration>
8+
<ProjectConfiguration Include="Release|Win32">
9+
<Configuration>Release</Configuration>
10+
<Platform>Win32</Platform>
11+
</ProjectConfiguration>
12+
<ProjectConfiguration Include="Debug|x64">
13+
<Configuration>Debug</Configuration>
14+
<Platform>x64</Platform>
15+
</ProjectConfiguration>
16+
<ProjectConfiguration Include="Release|x64">
17+
<Configuration>Release</Configuration>
18+
<Platform>x64</Platform>
19+
</ProjectConfiguration>
20+
</ItemGroup>
21+
<PropertyGroup Label="Globals">
22+
<VCProjectVersion>16.0</VCProjectVersion>
23+
<Keyword>Win32Proj</Keyword>
24+
<ProjectGuid>{8b8057bf-2d16-483e-9766-a5b3e30db44e}</ProjectGuid>
25+
<RootNamespace>My09INIpp</RootNamespace>
26+
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
27+
</PropertyGroup>
28+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
29+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
30+
<ConfigurationType>Application</ConfigurationType>
31+
<UseDebugLibraries>true</UseDebugLibraries>
32+
<PlatformToolset>v143</PlatformToolset>
33+
<CharacterSet>Unicode</CharacterSet>
34+
</PropertyGroup>
35+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
36+
<ConfigurationType>Application</ConfigurationType>
37+
<UseDebugLibraries>false</UseDebugLibraries>
38+
<PlatformToolset>v143</PlatformToolset>
39+
<WholeProgramOptimization>true</WholeProgramOptimization>
40+
<CharacterSet>Unicode</CharacterSet>
41+
</PropertyGroup>
42+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
43+
<ConfigurationType>Application</ConfigurationType>
44+
<UseDebugLibraries>true</UseDebugLibraries>
45+
<PlatformToolset>v143</PlatformToolset>
46+
<CharacterSet>Unicode</CharacterSet>
47+
</PropertyGroup>
48+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
49+
<ConfigurationType>Application</ConfigurationType>
50+
<UseDebugLibraries>false</UseDebugLibraries>
51+
<PlatformToolset>v143</PlatformToolset>
52+
<WholeProgramOptimization>true</WholeProgramOptimization>
53+
<CharacterSet>Unicode</CharacterSet>
54+
</PropertyGroup>
55+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
56+
<ImportGroup Label="ExtensionSettings">
57+
</ImportGroup>
58+
<ImportGroup Label="Shared">
59+
</ImportGroup>
60+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
61+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
62+
</ImportGroup>
63+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
64+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
65+
</ImportGroup>
66+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
67+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
68+
</ImportGroup>
69+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
70+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
71+
</ImportGroup>
72+
<PropertyGroup Label="UserMacros" />
73+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
74+
<TargetName>INIpp</TargetName>
75+
<OutDir>$(SolutionDir)build\bin\$(PlatformShortName)-$(Configuration)\</OutDir>
76+
<IntDir>$(SolutionDir)build\obj\$(PlatformShortName)-$(Configuration)\$(ProjectName)\</IntDir>
77+
</PropertyGroup>
78+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
79+
<TargetName>INIpp</TargetName>
80+
<OutDir>$(SolutionDir)build\bin\$(PlatformShortName)-$(Configuration)\</OutDir>
81+
<IntDir>$(SolutionDir)build\obj\$(PlatformShortName)-$(Configuration)\$(ProjectName)\</IntDir>
82+
</PropertyGroup>
83+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
84+
<TargetName>INIpp</TargetName>
85+
<OutDir>$(SolutionDir)build\bin\$(PlatformShortName)-$(Configuration)\</OutDir>
86+
<IntDir>$(SolutionDir)build\obj\$(PlatformShortName)-$(Configuration)\$(ProjectName)\</IntDir>
87+
</PropertyGroup>
88+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
89+
<TargetName>INIpp</TargetName>
90+
<OutDir>$(SolutionDir)build\bin\$(PlatformShortName)-$(Configuration)\</OutDir>
91+
<IntDir>$(SolutionDir)build\obj\$(PlatformShortName)-$(Configuration)\$(ProjectName)\</IntDir>
92+
</PropertyGroup>
93+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
94+
<ClCompile>
95+
<WarningLevel>Level3</WarningLevel>
96+
<SDLCheck>true</SDLCheck>
97+
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
98+
<ConformanceMode>true</ConformanceMode>
99+
<LanguageStandard>stdcpp20</LanguageStandard>
100+
</ClCompile>
101+
<Link>
102+
<SubSystem>Console</SubSystem>
103+
<GenerateDebugInformation>true</GenerateDebugInformation>
104+
</Link>
105+
</ItemDefinitionGroup>
106+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
107+
<ClCompile>
108+
<WarningLevel>Level3</WarningLevel>
109+
<FunctionLevelLinking>true</FunctionLevelLinking>
110+
<IntrinsicFunctions>true</IntrinsicFunctions>
111+
<SDLCheck>true</SDLCheck>
112+
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
113+
<ConformanceMode>true</ConformanceMode>
114+
<LanguageStandard>stdcpp20</LanguageStandard>
115+
</ClCompile>
116+
<Link>
117+
<SubSystem>Console</SubSystem>
118+
<EnableCOMDATFolding>true</EnableCOMDATFolding>
119+
<OptimizeReferences>true</OptimizeReferences>
120+
<GenerateDebugInformation>true</GenerateDebugInformation>
121+
</Link>
122+
</ItemDefinitionGroup>
123+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
124+
<ClCompile>
125+
<WarningLevel>Level3</WarningLevel>
126+
<SDLCheck>true</SDLCheck>
127+
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
128+
<ConformanceMode>true</ConformanceMode>
129+
<LanguageStandard>stdcpp20</LanguageStandard>
130+
</ClCompile>
131+
<Link>
132+
<SubSystem>Console</SubSystem>
133+
<GenerateDebugInformation>true</GenerateDebugInformation>
134+
</Link>
135+
</ItemDefinitionGroup>
136+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
137+
<ClCompile>
138+
<WarningLevel>Level3</WarningLevel>
139+
<FunctionLevelLinking>true</FunctionLevelLinking>
140+
<IntrinsicFunctions>true</IntrinsicFunctions>
141+
<SDLCheck>true</SDLCheck>
142+
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
143+
<ConformanceMode>true</ConformanceMode>
144+
<LanguageStandard>stdcpp20</LanguageStandard>
145+
</ClCompile>
146+
<Link>
147+
<SubSystem>Console</SubSystem>
148+
<EnableCOMDATFolding>true</EnableCOMDATFolding>
149+
<OptimizeReferences>true</OptimizeReferences>
150+
<GenerateDebugInformation>true</GenerateDebugInformation>
151+
</Link>
152+
</ItemDefinitionGroup>
153+
<ItemGroup>
154+
<ClCompile Include="INIpp.cpp" />
155+
<ClCompile Include="main.cpp" />
156+
</ItemGroup>
157+
<ItemGroup>
158+
<ClInclude Include="INIpp.hpp" />
159+
</ItemGroup>
160+
<ItemGroup>
161+
<None Include="config.ini" />
162+
</ItemGroup>
163+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
164+
<ImportGroup Label="ExtensionTargets">
165+
</ImportGroup>
166+
</Project>

09_INIpp/09_INIpp.vcxproj.filters

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<ItemGroup>
4+
<Filter Include="Source Files">
5+
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
6+
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
7+
</Filter>
8+
<Filter Include="Header Files">
9+
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
10+
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
11+
</Filter>
12+
<Filter Include="Resource Files">
13+
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
14+
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
15+
</Filter>
16+
</ItemGroup>
17+
<ItemGroup>
18+
<ClCompile Include="main.cpp">
19+
<Filter>Source Files</Filter>
20+
</ClCompile>
21+
<ClCompile Include="INIpp.cpp">
22+
<Filter>Source Files</Filter>
23+
</ClCompile>
24+
</ItemGroup>
25+
<ItemGroup>
26+
<ClInclude Include="INIpp.hpp">
27+
<Filter>Header Files</Filter>
28+
</ClInclude>
29+
</ItemGroup>
30+
<ItemGroup>
31+
<None Include="config.ini" />
32+
</ItemGroup>
33+
</Project>

09_INIpp/09_INIpp.vcxproj.user

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<ShowAllFiles>true</ShowAllFiles>
5+
</PropertyGroup>
6+
</Project>

09_INIpp/INIpp.cpp

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
#include "INIpp.hpp"
2+
3+
void INIpp::Parser::AddFile(const std::filesystem::path& path)
4+
{
5+
std::ifstream fileIn(path, std::ios::binary | std::ios::in);
6+
if (!fileIn.is_open())
7+
throw Exception(std::format("Can't open file \"{}\"", path.string()));
8+
9+
fileIn.seekg(0, std::ios::end);
10+
size_t fileSize = fileIn.tellg();
11+
fileIn.seekg(0, std::ios::beg);
12+
13+
std::string fileData(fileSize, ' ');
14+
fileIn.read(&fileData[0], fileSize);
15+
16+
AddString(fileData);
17+
}
18+
19+
void INIpp::Parser::AddString(const std::string_view& str)
20+
{
21+
Reset();
22+
for (char c : str)
23+
{
24+
ProcessChar(c);
25+
}
26+
}
27+
28+
void INIpp::Parser::Reset()
29+
{
30+
m_currentSection = "";
31+
m_currentKey = "";
32+
m_currentValue = "";
33+
m_state = State::ReadForData;
34+
}
35+
36+
void INIpp::Parser::ProcessChar(char c)
37+
{
38+
// Catch controle keys
39+
if (std::iscntrl(c))
40+
{
41+
switch (c)
42+
{
43+
case '\t':
44+
[[fallthrough]];
45+
case '\n':
46+
break;
47+
default:
48+
return;
49+
}
50+
}
51+
52+
// Normal char parsing
53+
switch (m_state)
54+
{
55+
case State::ReadForData:
56+
switch (c)
57+
{
58+
case ';':
59+
m_state = State::Comment;
60+
break;
61+
case '[':
62+
m_currentSection.clear();
63+
m_state = State::Section;
64+
break;
65+
case ' ':
66+
[[fallthrough]];
67+
case '\t':
68+
[[fallthrough]];
69+
case '\n':
70+
break;
71+
default:
72+
m_currentKey.clear();
73+
m_currentKey += c;
74+
m_state = State::KVKey;
75+
break;
76+
}
77+
break;
78+
case State::Comment:
79+
if (c == '\n')
80+
{
81+
m_state = State::ReadForData;
82+
}
83+
break;
84+
case State::Section:
85+
switch (c)
86+
{
87+
case ']':
88+
m_state = State::ReadForData;
89+
break;
90+
case '\n':
91+
[[fallthrough]];
92+
case '\t':
93+
throw Exception("Newlines or Tabs are not allowed in section names!");
94+
default:
95+
m_currentSection += c;
96+
break;
97+
}
98+
break;
99+
case State::KVKey:
100+
switch (c)
101+
{
102+
case ' ':
103+
m_state = State::KVKeyDone;
104+
break;
105+
case '\t':
106+
[[fallthrough]];
107+
case '\n':
108+
throw Exception("Newlines or Tabs are not allowed in the key!");
109+
default:
110+
m_currentKey += c;
111+
break;
112+
}
113+
break;
114+
case State::KVKeyDone:
115+
switch (c)
116+
{
117+
case ' ':
118+
[[fallthrough]];
119+
case '\t':
120+
break;
121+
case '\n':
122+
throw Exception("Every key need to have a value!");
123+
case '=':
124+
m_state = State::KVEqual;
125+
break;
126+
default:
127+
throw Exception("Keys are not allowed to have spaces in them!");
128+
}
129+
break;
130+
case State::KVEqual:
131+
switch (c)
132+
{
133+
case ' ':
134+
[[fallthrough]];
135+
case '\t':
136+
break;
137+
case '\n':
138+
throw Exception("Values can't be empty!");
139+
default:
140+
m_currentValue.clear();
141+
m_currentValue += c;
142+
m_state = State::KVValue;
143+
break;
144+
}
145+
break;
146+
case State::KVValue:
147+
if (c == '\n')
148+
{
149+
ParseKVPair(m_currentSection, m_currentKey, m_currentValue);
150+
m_state = State::ReadForData;
151+
}
152+
else
153+
{
154+
m_currentValue += c;
155+
}
156+
break;
157+
}
158+
}
159+
160+
void INIpp::SAXParser::ParseKVPair(const std::string& section, const std::string& key, const std::string& value)
161+
{
162+
if (m_callback)
163+
{
164+
m_callback(section, key, value);
165+
}
166+
}

0 commit comments

Comments
 (0)