Projektdateien hinzufügen.

This commit is contained in:
2025-02-01 00:28:38 +01:00
parent 8f27d6da31
commit ad40c514b6
7 changed files with 806 additions and 0 deletions

28
minipp.sln Normal file
View File

@@ -0,0 +1,28 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.12.35707.178 d17.12
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minipp", "minipp\minipp.vcxproj", "{F0C52CC0-DB78-4E1A-982F-EE565764C5AF}"
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
{F0C52CC0-DB78-4E1A-982F-EE565764C5AF}.Debug|x64.ActiveCfg = Debug|x64
{F0C52CC0-DB78-4E1A-982F-EE565764C5AF}.Debug|x64.Build.0 = Debug|x64
{F0C52CC0-DB78-4E1A-982F-EE565764C5AF}.Debug|x86.ActiveCfg = Debug|Win32
{F0C52CC0-DB78-4E1A-982F-EE565764C5AF}.Debug|x86.Build.0 = Debug|Win32
{F0C52CC0-DB78-4E1A-982F-EE565764C5AF}.Release|x64.ActiveCfg = Release|x64
{F0C52CC0-DB78-4E1A-982F-EE565764C5AF}.Release|x64.Build.0 = Release|x64
{F0C52CC0-DB78-4E1A-982F-EE565764C5AF}.Release|x86.ActiveCfg = Release|Win32
{F0C52CC0-DB78-4E1A-982F-EE565764C5AF}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

139
minipp/minipp.vcxproj Normal file
View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" 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>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{f0c52cc0-db78-4e1a-982f-ee565764c5af}</ProjectGuid>
<RootNamespace>minipp</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</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" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="minipp\minipp.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="test.cpp" />
<ClCompile Include="minipp\minipp.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Quelldateien">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Headerdateien">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Ressourcendateien">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="minipp\minipp.hpp">
<Filter>Headerdateien</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="minipp\minipp.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="test.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
</ItemGroup>
</Project>

436
minipp/minipp/minipp.cpp Normal file
View File

@@ -0,0 +1,436 @@
#include "minipp.hpp"
#include <fstream>
#define MINIPP_ENABLE_DEBUG_OUTPUT true
#if MINIPP_ENABLE_DEBUG_OUTPUT
#include <iostream>
#define COUT(msg) std::cout << msg << std::endl
#else
#define COUT(msg)
#endif
#define ASSERT(condition) if (!condition) abort();
#define COUT_SYNTAX_ERROR(line, msg) COUT("Error in line " << line << ": " << msg)
minipp::MiniPPFile::Section::~Section()
{
for (auto& pair : m_values)
delete pair.second;
for (auto& pair : m_subSections)
delete pair.second;
}
minipp::MiniPPFile::Section* minipp::MiniPPFile::Section::GetSubSection(const std::string& key, EResult* result) const noexcept
{
auto pathIndex = key.find('.');
std::string thisKey = key;
std::string rest;
if (pathIndex != std::string::npos)
{
thisKey = key.substr(0, pathIndex);
rest = key.substr(pathIndex + 1);
}
auto it = m_subSections.find(thisKey);
if (it == m_subSections.end())
{
COUT("Sub-Section not found: " << thisKey);
if (result != nullptr)
*result = EResult::SectionNotPresent;
return nullptr;
}
if (result != nullptr)
*result = EResult::Success;
if (rest.empty())
return it->second;
return it->second->GetSubSection(rest, result);
}
minipp::MiniPPFile::Section* minipp::MiniPPFile::Section::SetSubSection(const std::string& name, std::unique_ptr<Section> value, bool allowOverwrite, EResult* result) noexcept
{
if (m_subSections.find(name) != m_subSections.end())
if (!allowOverwrite)
{
if (result != nullptr)
*result = EResult::SectionAlreadyPresent;
return nullptr;
}
else
delete m_subSections[name];
auto val = value.release();
m_subSections[name] = val;
if (result != nullptr)
*result = EResult::Success;
return val;
}
minipp::MiniPPFile::StringValue::StringValue(const std::string& str) : m_value(str) {}
minipp::EResult minipp::MiniPPFile::StringValue::Parse(const std::string& str) noexcept
{
m_value = "";
for (size_t i = 0; i < str.size(); ++i)
{
if (str[i] == '\\')
{
if (i + 1 >= str.size())
return EResult::FormatError;
switch (str[i + 1])
{
case '\"':
m_value.push_back('\"');
break;
case 'n':
m_value.push_back('\n');
break;
case 't':
m_value.push_back('\t');
break;
case 'r':
m_value.push_back('\r');
break;
case '\\':
m_value.push_back('\\');
break;
default:
return EResult::FormatError;
}
++i;
}
else if (str[i] == '"')
return EResult::FormatError;
else
m_value.push_back(str[i]);
}
return EResult::Success;
}
minipp::EResult minipp::MiniPPFile::StringValue::ToString(std::string& destination) const noexcept
{
std::string sanitizedValue = m_value;
for (size_t i = 0; i < sanitizedValue.size(); ++i)
{
switch (sanitizedValue[i])
{
case '\n':
sanitizedValue.replace(i, 1, "\\n");
i++;
break;
case '\t':
sanitizedValue.replace(i, 1, "\\t");
i++;
break;
case '\r':
sanitizedValue.replace(i, 1, "\\r");
i++;
break;
case '\\':
sanitizedValue.insert(i, 1, '\\');
i++;
break;
case '\"':
sanitizedValue.insert(i, 1, '\\');
i++;
break;
}
}
destination = "\"" + sanitizedValue + "\"";
return EResult::Success;
}
const std::string& minipp::MiniPPFile::StringValue::GetValue() const noexcept
{
return m_value;
}
minipp::EResult minipp::MiniPPFile::Parse(const std::string& path) noexcept
{
std::ifstream ifs;
ifs.open(path);
if (!ifs.is_open())
return EResult::FileIOError;
int64_t lineCounter = 0;
Section* currentSection = nullptr;
std::string currentLine;
while (std::getline(ifs, currentLine))
{
++lineCounter;
Tools::StringTrim(currentLine);
if (currentLine.empty())
continue;
char firstChar = currentLine[0];
char lastChar = currentLine[currentLine.size() - 1];
if (firstChar == '#')
continue;
if (firstChar == '[')
{
if (lastChar != ']')
{
COUT_SYNTAX_ERROR(lineCounter, "Expected ']' at the end of the line.");
return EResult::FormatError;
}
std::string sectionName = currentLine.substr(1, currentLine.size() - 2);
Tools::StringTrim(sectionName);
if (sectionName.empty())
{
COUT_SYNTAX_ERROR(lineCounter, "Expected section path. Found empty section begin notation.");
return EResult::FormatError;
}
// Create section tree
Section* ubSection = &m_rootSection;
std::vector<std::string> sectionPath = Tools::SplitByDelimiter(sectionName, '.');
for (size_t i = 0; i < sectionPath.size(); ++i)
{
const std::string& sectionName = sectionPath[i];
if (!Tools::IsNameValid(sectionName))
{
COUT_SYNTAX_ERROR(lineCounter, "Invalid section name. (\"" << sectionName << "\") May only contain [a - z][A - Z][0 - 9] and _.");
return EResult::FormatError;
}
EResult result;
ubSection->SetSubSection(sectionName, std::make_unique<Section>(), false, &result); // if this fails, the section is already present
if (result == EResult::SectionAlreadyPresent && i == sectionPath.size() - 1)
{
COUT_SYNTAX_ERROR(lineCounter, "All (sub-) sections may only be defined once.");
return EResult::FormatError;
}
ubSection = ubSection->GetSubSection(sectionName, &result);
ASSERT(Tools::IsResultOk(result)); // should never happen
}
currentSection = ubSection;
continue;
}
if (currentSection == nullptr)
{
COUT_SYNTAX_ERROR(lineCounter, "Expected section begin before key-value pair.");
return EResult::FormatError;
}
int64_t keyValueDelimiterIndex = Tools::FirstIndexOf(currentLine, '=');
if (keyValueDelimiterIndex == -1)
{
COUT_SYNTAX_ERROR(lineCounter, "Expected '=' in line.");
return EResult::FormatError;
}
auto keyValuePair = Tools::SplitInTwo(currentLine, keyValueDelimiterIndex);
Tools::StringTrim(keyValuePair.first);
Tools::StringTrim(keyValuePair.second);
if (keyValuePair.first.empty())
{
COUT_SYNTAX_ERROR(lineCounter, "Expected key in line.");
return EResult::FormatError;
}
if (keyValuePair.second.empty())
{
COUT_SYNTAX_ERROR(lineCounter, "Empty keys are not allowed");
return EResult::FormatError;
}
std::string& value = keyValuePair.second;
char valueFirstChar = value.front();
char valueLastChar = value.back();
if (valueFirstChar == '"')
{
if (valueLastChar != '"')
{
COUT_SYNTAX_ERROR(lineCounter, "Expected '\"' at the end of the value.");
return EResult::FormatError;
}
// is string
value = value.substr(1, value.size() - 2);
StringValue strValue;
auto parseResult = strValue.Parse(value);
if (!Tools::IsResultOk(parseResult))
{
COUT_SYNTAX_ERROR(lineCounter, "Invalid string value.");
return EResult::FormatError;
}
currentSection->SetValue(keyValuePair.first, strValue, false);
continue;
}
else
{
IntValue intValue;
auto parseResult = intValue.Parse(value);
if (!Tools::IsResultOk(parseResult))
{
COUT_SYNTAX_ERROR(lineCounter, "Invalid integer value.");
return EResult::FormatError;
}
currentSection->SetValue(keyValuePair.first, intValue, false);
continue;
}
}
return EResult::Success;
}
void minipp::MiniPPFile::Write(const std::string& path) noexcept
{
}
bool minipp::MiniPPFile::Tools::StringStartsWith(const std::string& str, const std::string& beg)
{
if (str.size() < beg.size())
return false;
for (size_t i = 0; i < beg.size(); ++i)
if (str[i] != beg[i])
return false;
return true;
}
bool minipp::MiniPPFile::Tools::StringEndsWith(const std::string& str, const std::string& end)
{
if (str.size() < end.size())
return false;
for (size_t i = 0; i < end.size(); ++i)
if (str[str.size() - i - 1] != end[end.size() - i - 1])
return false;
return true;
}
void minipp::MiniPPFile::Tools::StringTrim(std::string& str)
{
if (str.empty())
return;
size_t start = 0;
size_t end = str.size() - 1;
while (str[start] == ' ' || str[start] == '\t')
start++;
while (str[end] == ' ' || str[end] == '\t')
end--;
str = str.substr(start, end - start + 1);
}
bool minipp::MiniPPFile::Tools::IsNameValid(const std::string& name) noexcept
{
for (const char c : name)
{
if (
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
(c == '_'))
continue;
return false;
}
return true;
}
int64_t minipp::MiniPPFile::Tools::FirstIndexOf(const std::string& str, char c) noexcept
{
int64_t index = 0;
for (const char ch : str)
{
if (ch == c)
return index;
++index;
}
return -1;
}
int64_t minipp::MiniPPFile::Tools::LastIndexOf(const std::string& str, char c) noexcept
{
int64_t index = str.size() - 1;
for (int64_t i = str.size() - 1; i >= 0; --i)
{
if (str[i] == c)
return index;
--index;
}
return -1;
}
std::pair<std::string, std::string> minipp::MiniPPFile::Tools::SplitInTwo(const std::string& str, int64_t firstLength) noexcept
{
return std::make_pair(str.substr(0, firstLength), str.substr(firstLength + 1));
}
std::vector<std::string> minipp::MiniPPFile::Tools::SplitByDelimiter(const std::string& str, char delimiter) noexcept
{
std::vector<std::string> elements;
std::string tmp;
for (const char c : str)
{
if (c == delimiter)
{
elements.push_back(tmp);
tmp.clear();
}
else
tmp.push_back(c);
}
if (!tmp.empty())
elements.push_back(tmp);
return elements;
}
bool minipp::MiniPPFile::Tools::IsResultOk(EResult result) noexcept
{
return static_cast<int32_t>(result) > 0;
}
void minipp::MiniPPFile::Tools::RemoveAll(std::string& str, char old)
{
str.erase(std::remove(str.begin(), str.end(), old), str.end());
}
bool minipp::MiniPPFile::Tools::IsIntegerDecimal(const std::string& str) noexcept
{
for (size_t i = 0; i < str.size(); ++i)
if (str[i] < '0' || str[i] > '9')
return false;
return true;
}
minipp::MiniPPFile::IntValue::IntValue(int64_t value) : m_value(value) {}
minipp::EResult minipp::MiniPPFile::IntValue::Parse(const std::string& str) noexcept
{
std::string sanitizedValue = str;
Tools::RemoveAll(sanitizedValue, '_');
if (sanitizedValue.empty())
return EResult::FormatError;
char lastCharacter = str.back();
auto rest = str.substr(0, str.size() - 1);
if (lastCharacter == 'h')
m_value = std::stoll(rest, nullptr, 16);
else if (lastCharacter == 'b')
m_value = std::stoll(rest, nullptr, 2);
else
{
if (!Tools::IsIntegerDecimal(sanitizedValue))
return EResult::FormatError;
m_value = std::stoll(sanitizedValue);
}
return EResult::Success;
}
minipp::EResult minipp::MiniPPFile::IntValue::ToString(std::string& destination) const noexcept
{
destination = std::to_string(m_value);
return EResult::Success;
}
int64_t minipp::MiniPPFile::IntValue::GetValue() const noexcept
{
return m_value;
}

141
minipp/minipp/minipp.hpp Normal file
View File

@@ -0,0 +1,141 @@
#pragma once
#include <cstdint>
#include <unordered_map>
#include <string>
#include <memory>
#include <utility>
#include <vector>
namespace minipp
{
enum class EResult
{
/* Errors */
KeyNotPresent = -1,
KeyAlreadyPresent = -2,
SectionNotPresent = -3,
SectionAlreadyPresent = -4,
FileIOError = -5,
InvalidDataType = -6,
FormatError = -7,
/* OK Codes*/
Success = 1,
ValueOverwritten,
ValueOverwrittenAndDataTypeChanged
};
class MiniPPFile
{
private:
class Tools
{
public:
static bool StringStartsWith(const std::string& str, const std::string& beg);
static bool StringEndsWith(const std::string& str, const std::string& end);
static void StringTrim(std::string& str);
static bool IsNameValid(const std::string& name) noexcept;
static int64_t FirstIndexOf(const std::string& str, char c) noexcept;
static int64_t LastIndexOf(const std::string& str, char c) noexcept;
static std::pair<std::string, std::string> SplitInTwo(const std::string& str, int64_t firstLength) noexcept;
static std::vector<std::string> SplitByDelimiter(const std::string& str, char delimiter) noexcept;
static bool IsResultOk(EResult result) noexcept;
static void RemoveAll(std::string& str, char old);
static bool IsIntegerDecimal(const std::string& str) noexcept;
};
public:
class Value
{
public:
virtual EResult Parse(const std::string& str) noexcept = 0;
virtual EResult ToString(std::string& destination) const noexcept = 0;
};
class StringValue : public Value
{
private:
std::string m_value;
public:
StringValue() = default;
StringValue(const std::string& str);
EResult Parse(const std::string& str) noexcept override;
EResult ToString(std::string& destination) const noexcept override;
const std::string& GetValue() const noexcept;
};
class IntValue : public Value
{
private:
int64_t m_value = 0;
public:
IntValue() = default;
IntValue(int64_t value);
EResult Parse(const std::string& str) noexcept override;
EResult ToString(std::string& destination) const noexcept override;
int64_t GetValue() const noexcept;
};
class Section
{
private:
std::unordered_map<std::string, Value*> m_values;
std::unordered_map<std::string, Section*> m_subSections;
public:
Section() = default;
~Section();
Section(const Section&) = delete;
Section& operator=(const Section&) = delete;
public:
template<typename T>
EResult GetValue(T** target, const std::string& key) noexcept
{
auto it = m_values.find(key);
if (it == m_values.end())
return EResult::KeyNotPresent;
auto val = dynamic_cast<T*>(it->second);
if (val == nullptr)
return EResult::InvalidDataType;
*target = val;
return EResult::Success;
}
template<typename T>
EResult SetValue(const std::string& name, const T& value, bool allowOverwrite = false) noexcept
{
if (m_values.find(name) != m_values.end())
if (!allowOverwrite)
return EResult::KeyAlreadyPresent;
else
delete m_values[name];
m_values[name] = new T(value);
return EResult::Success;
}
public:
Section* GetSubSection(const std::string& key, EResult* result = nullptr) const noexcept;
Section* SetSubSection(const std::string& name, std::unique_ptr<Section> value, bool allowOverwrite = false, EResult* result = nullptr) noexcept;
};
public:
MiniPPFile() = default;
private:
Section m_rootSection{};
public:
EResult Parse(const std::string& path) noexcept;
void Write(const std::string& path) noexcept;
public:
const Section& GetRoot() const noexcept { return m_rootSection; }
Section& GetRoot() noexcept { return m_rootSection; }
};
}

22
minipp/test.cpp Normal file
View File

@@ -0,0 +1,22 @@
#include "minipp/minipp.hpp"
int main()
{
minipp::MiniPPFile file;
auto result = file.Parse("test.mini");
auto& section = file.GetRoot();
minipp::MiniPPFile::Section* profileSection = section.GetSubSection("profile", &result);
minipp::MiniPPFile::IntValue* value;
auto result1 = profileSection->GetValue(&value, "window_width");
auto result2 = value->GetValue();
auto marianProfile = section.GetSubSection("profile.marian", &result);
minipp::MiniPPFile::StringValue* dockOutlinerType;
marianProfile->GetValue(&dockOutlinerType, "dock_outliner");
return 0;
}

10
minipp/test.mini Normal file
View File

@@ -0,0 +1,10 @@
[profile]
dock_outliner="left"
window_width=1000000b
window_height=fh
[profile.marian]
dock_outliner="ri\\ght\\"
[profile.toyb]
dock_outliner="top"