Added support for global options, and comments within a section.

This commit is contained in:
Nichole Mattera 2019-08-29 19:13:38 -04:00
parent ab894c3e9f
commit 67e165810e
17 changed files with 222 additions and 120 deletions

View File

@ -1,4 +1,4 @@
Copyright (c) 2019 Steven Mattera
Copyright (c) 2019 Nichole Mattera
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View File

@ -45,7 +45,7 @@ endif
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
LIBDIRS := $(PORTLIBS) $(LIBNX)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional

View File

@ -42,7 +42,10 @@ BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#ROMFS := romfs
APP_TITLE := SimpleIniParser Creating Example
APP_AUTHOR := Nichole Mattera
APP_VERSION := 2.0.0
#---------------------------------------------------------------------------------
# options for code generation
@ -61,6 +64,11 @@ LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*
LIBS := -lSimpleIniParser -lnx
ifneq (,$(shell which ccache))
CXX := $(shell which ccache) $(CXX)
CC := $(shell which ccache) $(CC)
endif
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib

View File

@ -1,6 +1,6 @@
/*
* SimpleIniParser
* Copyright (c) 2019 Steven Mattera
* Copyright (c) 2019 Nichole Mattera
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -28,31 +28,31 @@ int main(int argc, char **argv) {
Ini * hekateIni = new Ini();
IniSection * configSection = new IniSection(SECTION, "config");
configSection->options.push_back(new IniOption("autoboot", "1"));
configSection->options.push_back(new IniOption("autoboot_list", "0"));
configSection->options.push_back(new IniOption("bootwait", "5"));
configSection->options.push_back(new IniOption("customlogo", "1"));
configSection->options.push_back(new IniOption("verification", "1"));
configSection->options.push_back(new IniOption("backlight", "100"));
configSection->options.push_back(new IniOption("autohosoff", "0"));
configSection->options.push_back(new IniOption("autonogc", "1"));
IniSection * configSection = new IniSection(IniSectionType::Section, "config");
configSection->options.push_back(new IniOption(IniOptionType::Option, "autoboot", "1"));
configSection->options.push_back(new IniOption(IniOptionType::Option, "autoboot_list", "0"));
configSection->options.push_back(new IniOption(IniOptionType::Option, "bootwait", "5"));
configSection->options.push_back(new IniOption(IniOptionType::Option, "customlogo", "1"));
configSection->options.push_back(new IniOption(IniOptionType::Option, "verification", "1"));
configSection->options.push_back(new IniOption(IniOptionType::Option, "backlight", "100"));
configSection->options.push_back(new IniOption(IniOptionType::Option, "autohosoff", "0"));
configSection->options.push_back(new IniOption(IniOptionType::Option, "autonogc", "1"));
hekateIni->sections.push_back(configSection);
hekateIni->sections.push_back(new IniSection(HEKATE_CAPTION, "CFW"));
hekateIni->sections.push_back(new IniSection(IniSectionType::HekateCaption, "CFW"));
IniSection * cfwSection = new IniSection(SECTION, "CFW");
cfwSection->options.push_back(new IniOption("fss0", "atmosphere/fusee-secondary.bin"));
cfwSection->options.push_back(new IniOption("kip1patch", "nosigchk"));
cfwSection->options.push_back(new IniOption("atmosphere", "1"));
cfwSection->options.push_back(new IniOption("logopath", "bootloader/bootlogo.bmp"));
IniSection * cfwSection = new IniSection(IniSectionType::Section, "CFW");
cfwSection->options.push_back(new IniOption(IniOptionType::Option, "fss0", "atmosphere/fusee-secondary.bin"));
cfwSection->options.push_back(new IniOption(IniOptionType::Option, "kip1patch", "nosigchk"));
cfwSection->options.push_back(new IniOption(IniOptionType::Option, "atmosphere", "1"));
cfwSection->options.push_back(new IniOption(IniOptionType::Option, "logopath", "bootloader/bootlogo.bmp"));
hekateIni->sections.push_back(cfwSection);
hekateIni->sections.push_back(new IniSection(HEKATE_CAPTION, "Stock"));
hekateIni->sections.push_back(new IniSection(IniSectionType::HekateCaption, "Stock"));
IniSection * stockSection = new IniSection(SECTION, "Stock");
stockSection->options.push_back(new IniOption("fss0", "atmosphere/fusee-secondary.bin"));
stockSection->options.push_back(new IniOption("stock", "1"));
IniSection * stockSection = new IniSection(IniSectionType::Section, "Stock");
stockSection->options.push_back(new IniOption(IniOptionType::Option, "fss0", "atmosphere/fusee-secondary.bin"));
stockSection->options.push_back(new IniOption(IniOptionType::Option, "stock", "1"));
hekateIni->sections.push_back(stockSection);
if (hekateIni->writeToFile("sdmc:/example.ini")) {

View File

@ -44,6 +44,10 @@ DATA := data
INCLUDES := include
ROMFS := romfs
APP_TITLE := SimpleIniParser Editing Example
APP_AUTHOR := Nichole Mattera
APP_VERSION := 2.0.0
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
@ -61,6 +65,11 @@ LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*
LIBS := -lSimpleIniParser -lnx
ifneq (,$(shell which ccache))
CXX := $(shell which ccache) $(CXX)
CC := $(shell which ccache) $(CC)
endif
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib

View File

@ -1,19 +1,21 @@
# Sample Config
global_setting=1
; Comments
global_setting_two=2
[config]
autoboot=1
autoboot_list=0
bootwait=5
customlogo=1
verification=1
backlight=100
autohosoff=0
autonogc=1
{AtlasNX/Kosmos}
; Custom Firmwares
[CFW]
fss0=atmosphere/fusee-secondary.bin
kip1patch=nosigchk
# Option Comment Test
atmosphere=1
logopath=bootloader/bootlogo1.bmp
logopath=bootloader/bootlogo2.bmp

View File

@ -1,6 +1,6 @@
/*
* SimpleIniParser
* Copyright (c) 2019 Steven Mattera
* Copyright (c) 2019 Nichole Mattera
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -33,7 +33,7 @@ int main(int argc, char **argv) {
cout << "Unable to initialize romfs.\n";
}
else {
copy_file("romfs:/hekate_ipl.ini", "sdmc:/example1.ini");
copy_file("romfs:/config.ini", "sdmc:/example1.ini");
Ini * exampleIni = Ini::parseFile("sdmc:/example1.ini");
exampleIni->sections.pop_back();

View File

@ -44,6 +44,10 @@ DATA := data
INCLUDES := include
ROMFS := romfs
APP_TITLE := SimpleIniParser Reading Example
APP_AUTHOR := Nichole Mattera
APP_VERSION := 2.0.0
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
@ -61,6 +65,11 @@ LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*
LIBS := -lSimpleIniParser -lnx
ifneq (,$(shell which ccache))
CXX := $(shell which ccache) $(CXX)
CC := $(shell which ccache) $(CC)
endif
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib

View File

@ -1,19 +1,21 @@
# Sample Config
global_setting=1
; Comments
global_setting_two=2
[config]
autoboot=1
autoboot_list=0
bootwait=5
customlogo=1
verification=1
backlight=100
autohosoff=0
autonogc=1
{AtlasNX/Kosmos}
; Custom Firmwares
[CFW]
fss0=atmosphere/fusee-secondary.bin
kip1patch=nosigchk
# Option Comment Test
atmosphere=1
logopath=bootloader/bootlogo1.bmp
logopath=bootloader/bootlogo2.bmp

View File

@ -1,6 +1,6 @@
/*
* SimpleIniParser
* Copyright (c) 2019 Steven Mattera
* Copyright (c) 2019 Nichole Mattera
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -23,6 +23,48 @@
using namespace simpleIniParser;
using namespace std;
void writeOption(IniOption * option, bool withTab) {
switch (option->type) {
case IniOptionType::SemicolonComment:
cout << ((withTab) ? "\t" : "") << "Type: Semicolon Comment, Value: \"" << option->value << "\"\n";
break;
case IniOptionType::HashtagComment:
cout << ((withTab) ? "\t" : "") << "Type: Hashtag Comment, Value: \"" << option->value << "\"\n";
break;
default:
cout << ((withTab) ? "\t" : "") << "Type: Option, Key: \"" << option->key << "\", Value: \"" << option->value << "\"\n";
break;
}
}
void writeSection(IniSection * section) {
switch (section->type) {
case IniSectionType::SemicolonComment:
cout << "Type: Semicolon Comment, Value: \"" << section->value << "\"\n";
break;
case IniSectionType::HashtagComment:
cout << "Type: Hashtag Comment, Value: \"" << section->value << "\"\n";
break;
case IniSectionType::HekateCaption:
cout << "Type: Hekate Caption, Value: \"" << section->value << "\"\n";
break;
default:
cout << "Type: Section, Value: \"" << section->value << "\"\n";
break;
}
for (auto const& option : section->options) {
writeOption(option, true);
}
cout << "\n";
}
int main(int argc, char **argv) {
consoleInit(NULL);
@ -31,50 +73,29 @@ int main(int argc, char **argv) {
cout << "Unable to initialize romfs.\n";
}
else {
Ini * hekateIni = Ini::parseFile("romfs:/hekate_ipl.ini");
Ini * config = Ini::parseFile("romfs:/config.ini");
cout << "Reading through an INI file.\n";
cout << "=====================================================\n\n";
for (auto const& section : hekateIni->sections) {
switch (section->type) {
case SECTION:
cout << "Type: Section | Value: \"" << section->value << "\"\n";
cout << "-----------------------------------------------------\n";
break;
case SEMICOLON_COMMENT:
cout << "Type: Semicolon Comment | Value: \"" << section->value << "\"\n";
cout << "-----------------------------------------------------\n";
break;
case HASHTAG_COMMENT:
cout << "Type: Hashtag Comment | Value: \"" << section->value << "\"\n";
cout << "-----------------------------------------------------\n";
break;
case HEKATE_CAPTION:
cout << "Type: Hekate Caption | Value: \"" << section->value << "\"\n";
cout << "-----------------------------------------------------\n";
break;
default:
break;
}
for (auto const& option : section->options) {
cout << "Key: \"" << option->key << "\" | Value: \"" << option->value << "\"\n";
}
for (auto const& option : config->options) {
writeOption(option, false);
}
if (config->options.size() > 0)
cout << "\n";
for (auto const& section : config->sections) {
writeSection(section);
}
cout << "\nGet a specific option from a specific section.\n";
cout << "=====================================================\n\n";
IniOption * option = hekateIni->findSection("config")->findFirstOption("aUtOnOgC", false);
IniOption * option = config->findSection("config")->findFirstOption("cUsToMlOgO", false);
cout << "Key: \"" << option->key << "\" | Value: \"" << option->value << "\"\n\n";
delete hekateIni;
delete config;
}
cout << "\nPress any key to close.\n";

View File

@ -1,6 +1,6 @@
/*
* SimpleIniParser
* Copyright (c) 2019 Steven Mattera
* Copyright (c) 2019 Nichole Mattera
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above

View File

@ -1,6 +1,6 @@
/*
* SimpleIniParser
* Copyright (c) 2019 Steven Mattera
* Copyright (c) 2019 Nichole Mattera
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -21,14 +21,17 @@
#include <string>
#include "IniSection.hpp"
#include "IniOption.hpp"
namespace simpleIniParser {
class Ini {
public:
std::vector<IniOption *> options;
std::vector<IniSection *> sections;
~Ini();
std::string build();
IniOption * findFirstOption(std::string key, bool caseSensitive = true);
IniSection * findSection(std::string name, bool caseSensitive = true);
bool writeToFile(std::string path);
static Ini * parseFile(std::string path);

View File

@ -1,6 +1,6 @@
/*
* SimpleIniParser
* Copyright (c) 2019 Steven Mattera
* Copyright (c) 2019 Nichole Mattera
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -20,12 +20,19 @@
#include <string>
namespace simpleIniParser {
enum class IniOptionType {
Option,
SemicolonComment,
HashtagComment,
};
class IniOption {
public:
IniOptionType type;
std::string key;
std::string value;
IniOption(std::string name, std::string val);
IniOption(IniOptionType type, std::string key, std::string val);
std::string build();
static IniOption * parse(std::string line);
};

View File

@ -1,6 +1,6 @@
/*
* SimpleIniParser
* Copyright (c) 2019 Steven Mattera
* Copyright (c) 2019 Nichole Mattera
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -23,13 +23,12 @@
#include "IniOption.hpp"
namespace simpleIniParser {
typedef enum {
SECTION,
SEMICOLON_COMMENT,
HASHTAG_COMMENT,
HEKATE_CAPTION,
BLANK_LINE
} IniSectionType;
enum class IniSectionType {
Section,
SemicolonComment,
HashtagComment,
HekateCaption,
};
class IniSection {
public:
@ -41,6 +40,6 @@ namespace simpleIniParser {
~IniSection();
IniOption * findFirstOption(std::string key, bool caseSensitive = true);
std::string build();
static IniSection * parse(std::string line);
static IniSection * parse(std::string line, bool parseComments);
};
}

View File

@ -1,6 +1,6 @@
/*
* SimpleIniParser
* Copyright (c) 2019 Steven Mattera
* Copyright (c) 2019 Nichole Mattera
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -18,6 +18,7 @@
#include <algorithm>
#include <fstream>
#include <iostream>
#include <switch.h>
#include "Ini.hpp"
#include "IniOption.hpp"
@ -39,13 +40,35 @@ namespace simpleIniParser {
string Ini::build() {
string result;
for (IniSection * section : sections) {
result += section->build() + "\n";
for (auto const& option : options) {
result += option->build();
}
for (auto const& section : sections) {
result += section->build();
}
return result;
}
IniOption * Ini::findFirstOption(string key, bool caseSensitive) {
if (!caseSensitive) {
IniStringHelper::toupper(key);
}
auto it = find_if(options.begin(), options.end(), [&key, &caseSensitive](const IniOption * obj) {
if (!caseSensitive) {
return IniStringHelper::toupper_copy(obj->key) == key;
}
return obj->key == key;
});
if (it == options.end())
return nullptr;
return (*it);
}
IniSection * Ini::findSection(string name, bool caseSensitive) {
if (!caseSensitive) {
IniStringHelper::toupper(name);
@ -74,6 +97,8 @@ namespace simpleIniParser {
file.flush();
file.close();
fsdevCommitDevice("sdmc");
return true;
}
@ -90,15 +115,18 @@ namespace simpleIniParser {
if (line.size() == 0)
continue;
IniSection * section = IniSection::parse(line);
bool shouldParseCommentsAsSection = ini->sections.size() != 0 && ini->sections.back()->type != IniSectionType::Section;
IniSection * section = IniSection::parse(line, shouldParseCommentsAsSection);
if (section != nullptr) {
ini->sections.push_back(section);
}
else if (ini->sections.size() != 0 && ini->sections.back()->type == SECTION) {
} else {
IniOption * option = IniOption::parse(line);
if (option != nullptr)
if (option != nullptr && ini->sections.size() == 0) {
ini->options.push_back(option);
} else if (option != nullptr && ini->sections.size() != 0 && ini->sections.back()->type == IniSectionType::Section) {
ini->sections.back()->options.push_back(option);
}
}
}

View File

@ -1,6 +1,6 @@
/*
* SimpleIniParser
* Copyright (c) 2019 Steven Mattera
* Copyright (c) 2019 Nichole Mattera
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -21,21 +21,37 @@
using namespace std;
namespace simpleIniParser {
IniOption::IniOption(string name, string val) {
key = name;
value = val;
IniOption::IniOption(IniOptionType t, string k, string v) {
type = t;
key = k;
value = v;
}
string IniOption::build() {
return key + '=' + value;
switch (type) {
case IniOptionType::SemicolonComment:
return "; " + value + "\n";
case IniOptionType::HashtagComment:
return "# " + value + "\n";
default:
return key + "=" + value + "\n";
}
}
IniOption * IniOption::parse(string line) {
size_t pos = line.find('=');
if (pos != string::npos && pos > 0) {
return new IniOption(IniStringHelper::rtrim_copy(line.substr(0, pos)), IniStringHelper::ltrim_copy(line.substr(pos + 1)));
if (line.at(0) == ';') {
return new IniOption(IniOptionType::SemicolonComment, "", IniStringHelper::trim_copy(line.substr(1, line.size() - 1)));
} else if (line.at(0) == '#') {
return new IniOption(IniOptionType::HashtagComment, "", IniStringHelper::trim_copy(line.substr(1, line.size() - 1)));
} else {
return nullptr;
size_t pos = line.find('=');
if (pos != string::npos && pos > 0) {
return new IniOption(IniOptionType::Option, IniStringHelper::rtrim_copy(line.substr(0, pos)), IniStringHelper::ltrim_copy(line.substr(pos + 1)));
} else {
return nullptr;
}
}
}
}

View File

@ -1,6 +1,6 @@
/*
* SimpleIniParser
* Copyright (c) 2019 Steven Mattera
* Copyright (c) 2019 Nichole Mattera
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -58,38 +58,36 @@ namespace simpleIniParser {
}
string IniSection::build() {
if (type == HEKATE_CAPTION)
return "{" + value + "}\n";
if (type == SEMICOLON_COMMENT)
return ";" + value + "\n";
if (type == HASHTAG_COMMENT)
return "#" + value + "\n";
switch (type) {
case IniSectionType::HekateCaption:
return "\n{" + value + "}\n";
if (type == BLANK_LINE)
return "\n";
case IniSectionType::SemicolonComment:
return "\n; " + value + "\n";
string result = "[" + value + "]\n";
case IniSectionType::HashtagComment:
return "\n# " + value + "\n";
for (IniOption * option : options) {
result += option->build() + "\n";
default:
string result = "\n[" + value + "]\n";
for (auto const& option : options) {
result += option->build();
}
return result;
}
return result;
}
IniSection * IniSection::parse(string line) {
IniSection * IniSection::parse(string line, bool parseComments) {
if (line.at(0) == '{' && line.at(line.size() - 1) == '}') {
return new IniSection(HEKATE_CAPTION, line.substr(1, line.size() - 2));
} else if (line.at(0) == ';') {
return new IniSection(SEMICOLON_COMMENT, line.substr(1, line.size() - 1));
} else if (line.at(0) == '#') {
return new IniSection(HASHTAG_COMMENT, line.substr(1, line.size() - 1));
return new IniSection(IniSectionType::HekateCaption, IniStringHelper::trim_copy(line.substr(1, line.size() - 2)));
} else if (parseComments && line.at(0) == ';') {
return new IniSection(IniSectionType::SemicolonComment, IniStringHelper::trim_copy(line.substr(1, line.size() - 1)));
} else if (parseComments && line.at(0) == '#') {
return new IniSection(IniSectionType::HashtagComment, IniStringHelper::trim_copy(line.substr(1, line.size() - 1)));
} else if (line.at(0) == '[' && line.at(line.size() - 1) == ']') {
return new IniSection(SECTION, line.substr(1, line.size() - 2));
} else if (line.size() == 0) {
return new IniSection(BLANK_LINE, "");
return new IniSection(IniSectionType::Section, IniStringHelper::trim_copy(line.substr(1, line.size() - 2)));
} else {
return nullptr;
}