Skip to content

Commit

Permalink
Fix key validation
Browse files Browse the repository at this point in the history
  • Loading branch information
DefinitelyNotSimon13 committed Apr 26, 2024
1 parent cb1aaf6 commit e1b675b
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 116 deletions.
202 changes: 101 additions & 101 deletions src/sources/CommandLineHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,119 +20,119 @@

namespace cli {
void CommandLineHandler::printHelp() {
LOG_INFO << "Printing help message...";
OUTPUT << BOLD << "Usage:\n"
<< RESET << "----------\n"
<< config::EXECUTABLE_NAME << " [options] [filenames]\n"
<< "\n"
<< BOLD << "Options:\n"
<< RESET << "----------\n"
<< "-o, --outdir\t [path]\t\tOutput the batch file to the given "
"dir\n"
<< "-h, --help\t\t\tPrint this help message\n"
<< "-v, --version\t\t\tPrint the version number\n"
<< "-c, --credits\t\t\tPrint the credits\n\n"
<< " --verbose\t\t\tStart the application in verbose mode\n"
<< ITALIC
<< " \t\t\tNote: Verbose flag should be passed first!\n\n"
<< RESET << BOLD << "Filenames:\n"
<< RESET << "----------\n"
<< "The json files to be processed into batch files.\n"
<< "Multiple files should be seperated by spaces!\n\n";
exit(0);
LOG_INFO << "Printing help message...";
OUTPUT << BOLD << "Usage:\n"
<< RESET << "----------\n"
<< config::EXECUTABLE_NAME << " [options] [filenames]\n"
<< "\n"
<< BOLD << "Options:\n"
<< RESET << "----------\n"
<< "-o, --outdir\t [path]\t\tOutput the batch file to the given "
"dir\n"
<< "-h, --help\t\t\tPrint this help message\n"
<< "-v, --version\t\t\tPrint the version number\n"
<< "-c, --credits\t\t\tPrint the credits\n\n"
<< " --verbose\t\t\tStart the application in verbose mode\n"
<< ITALIC
<< " \t\t\tNote: Verbose flag should be passed first!\n\n"
<< RESET << BOLD << "Filenames:\n"
<< RESET << "----------\n"
<< "The json files to be processed into batch files.\n"
<< "Multiple files should be seperated by spaces!\n\n";
exit(0);
}
void CommandLineHandler::printVersion() {
LOG_INFO << "Printing version number...";
OUTPUT << config::PROJECT_NAME << " v" << config::MAJOR_VERSION << "."
<< config::MINOR_VERSION << "." << config::PATCH_VERSION << "\n";
exit(0);
LOG_INFO << "Printing version number...";
OUTPUT << config::PROJECT_NAME << " v" << config::MAJOR_VERSION << "."
<< config::MINOR_VERSION << "." << config::PATCH_VERSION << "\n";
exit(0);
}
void CommandLineHandler::printCredits() {
LOG_INFO << "Printing credits...";
OUTPUT << BOLD << "Project information:\n"
<< RESET << "----------\n"
<< CYAN << BOLD << config::PROJECT_NAME << RESET << " v"
<< config::MAJOR_VERSION << "." << config::MINOR_VERSION << "."
<< config::PATCH_VERSION << "\n"
<< "\n"
<< config::DESCRIPTION << "\n"
<< "\n"
<< GREEN << "Authors: " << RESET << ITALIC << config::AUTHORS << RESET
<< "\n"
<< GREEN << "Documentation: " << RESET << ITALIC
<< config::HOMEPAGE_URL << RESET << GREEN << "\nContact: " << RESET
<< ITALIC << "[email protected]" << "\n";
exit(0);
LOG_INFO << "Printing credits...";
OUTPUT << BOLD << "Project information:\n"
<< RESET << "----------\n"
<< CYAN << BOLD << config::PROJECT_NAME << RESET << " v"
<< config::MAJOR_VERSION << "." << config::MINOR_VERSION << "."
<< config::PATCH_VERSION << "\n"
<< "\n"
<< config::DESCRIPTION << "\n"
<< "\n"
<< GREEN << "Authors: " << RESET << ITALIC << config::AUTHORS << RESET
<< "\n"
<< GREEN << "Documentation: " << RESET << ITALIC
<< config::HOMEPAGE_URL << RESET << GREEN << "\nContact: " << RESET
<< ITALIC << "[email protected]" << "\n";
exit(0);
}

std::tuple<std::optional<std::string>, std::vector<std::string>>
CommandLineHandler::parseArguments(int argc, char *argv[]) {
LOG_INFO << "Parsing arguments...";
std::vector<std::string> files;
std::optional<std::string> outDir;

while (true) {
int optIndex = -1;
struct option longOption = {};
const auto result = getopt_long(argc, argv, "hvco:", options, &optIndex);

if (result == -1) {
LOG_INFO << "End of options reached";
break;
LOG_INFO << "Parsing arguments...";
std::vector<std::string> files;
std::optional<std::string> outDir;

while (true) {
int optIndex = -1;
struct option longOption = {};
const auto result = getopt_long(argc, argv, "hvco:", options, &optIndex);

if (result == -1) {
LOG_INFO << "End of options reached";
break;
}

switch (result) {
case '?':
LOG_ERROR << "Invalid Option (argument)";
CommandLineHandler::printHelp();

case 'h':
LOG_INFO << "Help option detected";
CommandLineHandler::printHelp();

case 'v':
LOG_INFO << "Version option detected";
CommandLineHandler::printVersion();

case 'c':
LOG_INFO << "Credit option detected";
CommandLineHandler::printCredits();

case 'o':
LOG_INFO << "Output option detected";
outDir = optarg;
break;

case 0:
LOG_INFO << "Long option without short version detected";
longOption = options[optIndex];
LOG_INFO << "Option: " << longOption.name << " given";

if (strcmp(longOption.name, "verbose") == 0) {
logging::setVerboseMode(true);
LOG_INFO << "Verbose mode activated";
}

break;

default:
LOG_ERROR << "Default case for options reached!";
break;
}
}

switch (result) {
case '?':
LOG_ERROR << "Invalid Option (argument)";
CommandLineHandler::printHelp();
LOG_INFO << "Options have been parsed";
LOG_INFO << "Checking for arguments...";

case 'h':
LOG_INFO << "Help option detected";
CommandLineHandler::printHelp();

case 'v':
LOG_INFO << "Version option detected";
CommandLineHandler::printVersion();

case 'c':
LOG_INFO << "Credit option detected";
CommandLineHandler::printCredits();

case 'o':
LOG_INFO << "Output option detected";
outDir = optarg;
break;

case 0:
LOG_INFO << "Long option without short version detected";
longOption = options[optIndex];
LOG_INFO << "Option: " << longOption.name << " given";

if (strcmp(longOption.name, "verbose") == 0) {
logging::setVerboseMode(true);
LOG_INFO << "Verbose mode activated";
}

break;

default:
LOG_ERROR << "Default case for options reached!";
break;
// Loop for {reqFunc5}
while (optind < argc) {
LOG_INFO << "Adding file: " << argv[optind];
// Vector for {reqFunc7}
files.emplace_back(argv[optind++]);
}
}

LOG_INFO << "Options have been parsed";
LOG_INFO << "Checking for arguments...";

// Loop for {reqFunc5}
while (optind < argc) {
LOG_INFO << "Adding file: " << argv[optind];
// Vector for {reqFunc7}
files.emplace_back(argv[optind++]);
}

LOG_DEBUG << files.size();
LOG_INFO << "Arguments and options have been parsed";
return {outDir, files};
LOG_DEBUG << files.size();
LOG_INFO << "Arguments and options have been parsed";
return {outDir, files};
}
} // namespace cli
39 changes: 24 additions & 15 deletions src/sources/KeyValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,36 +23,43 @@ KeyValidator &KeyValidator::getInstance() {
return keyValidator;
}

std::vector<std::tuple<int, std::string>> KeyValidator::validateKeys(
const Json::Value &root,
const std::string &filename) {
std::vector<std::tuple<int, std::string>>
KeyValidator::validateKeys(const Json::Value &root,
const std::string &filename) {
LOG_INFO << "Validating keys for file " << filename;
std::vector<std::tuple<int, std::string>> wrongKeys =
getWrongKeys(root, filename);

// Inline declaration to prevent leaking in outer scope
for (Json::Value entries = root.get("entries", "");
const auto &entry : entries) {
LOG_INFO << "Validating entry";
const auto entryKeys = entry.getMemberNames();
// Create a set of the entry keys for faster lookup (O(1) instead of O(n))
std::unordered_set<std::string> entryKeysSet(entryKeys.begin(),
entryKeys.end());

const auto wrongEntries = validateEntries(filename, entryKeysSet);

// Combine wrong keys
wrongKeys.insert(wrongKeys.end(), wrongEntries.begin(), wrongEntries.end());
// Validate that each entry has it's necessary keys

LOG_INFO << "Validating types for entry";
validateTypes(filename, entry, entryKeysSet);
}

return wrongKeys;
}

std::vector<std::tuple<int, std::string>> KeyValidator::getWrongKeys(
const Json::Value &root,
const std::string &filename) const {
std::vector<std::tuple<int, std::string>>
KeyValidator::getWrongKeys(const Json::Value &root,
const std::string &filename) const {
std::vector<std::tuple<int, std::string>> wrongKeys = {};

LOG_INFO << "Checcking for wrong keys in file " << filename << "!";
for (const auto &key : root.getMemberNames()) {
if (!validKeys.contains(key)) {
LOG_WARNING << "Found wrong key " << key << "!";
const auto error = getUnknownKeyLine(filename, key);

if (!error.has_value()) {
Expand All @@ -74,6 +81,7 @@ std::vector<std::tuple<int, std::string>> KeyValidator::validateEntries(
std::vector<std::tuple<int, std::string>> wrongKeys = {};

for (const auto &key : entryKeys) {
LOG_INFO << "Checking key " << key << "!";
if (!validEntryKeys.contains(key)) {
const auto error = getUnknownKeyLine(filename, key);

Expand All @@ -94,14 +102,14 @@ void KeyValidator::validateTypes(
const std::unordered_set<std::string> &entryKeys) {
// Gett the type of the entry - error if not found
const std::string type = entry.get("type", "ERROR").asString();
LOG_INFO << "Validating type " << type;

// If the type is not found, throw an exception
if (type == "ERROR") {
throw exceptions::MissingTypeException();
// If the type is not known, throw an exception
// @note This should already have been checked
}
else if (typeToKeys.contains(type)) {
} else if (!typeToKeys.contains(type)) {
const std::optional<int> line =
getUnknownKeyLine(filename, std::string(type));

Expand All @@ -111,18 +119,19 @@ void KeyValidator::validateTypes(

throw exceptions::InvalidTypeException(std::string(type), line.value());
// If the type is known, check if all necessary keys are present
}
else {
} else {
for (const auto &key : typeToKeys[type]) {
if (entryKeys.contains(key)) {
throw exceptions::MissingKeyException(key, std::string(type));
LOG_INFO << "Checking key " << key << " for type " << type;
if (!entryKeys.contains(key)) {
throw exceptions::MissingKeyException(key, type);
}
}
}
}

std::optional<int> KeyValidator::getUnknownKeyLine(const std::string &filename,
const std::string &wrongKey) {
std::optional<int>
KeyValidator::getUnknownKeyLine(const std::string &filename,
const std::string &wrongKey) {
std::ifstream file(filename);

if (!file.is_open()) {
Expand Down

0 comments on commit e1b675b

Please sign in to comment.