From 390087fc355c4251308638523990e36f994c4b57 Mon Sep 17 00:00:00 2001 From: BodgeMaster <> Date: Thu, 14 Jul 2022 04:57:48 +0200 Subject: [PATCH] lib/cli: finish initial implementation This should be all functionality that is needed for now. The next step is building unit tests to check that everything works correctly. Who am I kidding? There will most certainly be bugs in there given that this code has been typed out without ever being run. --- src/lib/cli.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++- src/lib/cli.h++ | 10 ++++----- src/lib/error.h++ | 3 +++ 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/lib/cli.cpp b/src/lib/cli.cpp index 539e942..238b512 100644 --- a/src/lib/cli.cpp +++ b/src/lib/cli.cpp @@ -56,6 +56,7 @@ namespace CLI { ArgumentsParser::ArgumentsParser(int argc, char* argv[], std::vector flags, std::vector unpositionalArguments, std::vector positionalArguments) { this->wrongUsage = false; this->wrongUsageMessages = std::vector(); + this->programName = std::string(argv[0]); this->positionalArguments = positionalArguments; // create lookup tables for all flags and unpositional arguments // by their names @@ -78,7 +79,7 @@ namespace CLI { UnpositionalArgument* argumentWaitingForValue = nullptr; std::vector::size_type positionalArgumentCounter = 0; - for (int i=0; i ArgumentsParser::getProgramName() { + if (this->wrongUsage) { + return ErrorOr(true, ErrorCodes::WRONG_USAGE, this->programName); + } + return ErrorOr(this->programName); + } + + ErrorOr ArgumentsParser::getFlag(int argc, char* argv[], char shortName) { + if (!this->flagsByShortName.contains(shortName)) return ErrorOr(true, ErrorCodes::UNKNOWN_KEY, false); + if (this->wrongUsage) { + return ErrorOr(true, ErrorCodes::WRONG_USAGE, this->flagsByShortName[shortName]->present); + } + return ErrorOr(this->flagsByShortName[shortName]->present); + } + + ErrorOr ArgumentsParser::getFlag(int argc, char* argv[], std::string longName) { + if (!this->flagsByLongName.contains(longName)) return ErrorOr(true, ErrorCodes::UNKNOWN_KEY, false); + if (this->wrongUsage) { + return ErrorOr(true, ErrorCodes::WRONG_USAGE, this->flagsByLongName[longName]->present); + } + return ErrorOr(this->flagsByLongName[longName]->present); + } + + ErrorOr ArgumentsParser::getPositionalArgument(int argc, char* argv[], std::vector::size_type position){ + if (position >= this->positionalArguments.size()) return ErrorOr(true, ErrorCodes::OUT_OF_RANGE, std::string("")); + if (this->wrongUsage) { + if (this->positionalArguments.at(position).present) return ErrorOr(true, ErrorCodes::WRONG_USAGE, this->positionalArguments.at(position).value); + else return ErrorOr(true, ErrorCodes::NOT_PRESENT, std::string("")); + } + return ErrorOr(this->positionalArguments.at(position).value); + } + + ErrorOr ArgumentsParser::getUnpositionalArgument(int argc, char* argv[], char shortName) { + if (!this->argumentsByShortName.contains(shortName)) return ErrorOr(true, ErrorCodes::UNKNOWN_KEY, std::string("")); + if (this-wrongUsage) { + if (this->argumentsByShortName[shortName]->present) return ErrorOr(true, ErrorCodes::WRONG_USAGE, this->argumentsByShortName[shortName]->value); + else return ErrorOr(true, ErrorCodes::NOT_PRESENT, std::string("")); + } + if (this->argumentsByShortName[shortName]->present) return ErrorOr(this->argumentsByShortName[shortName]->value); + // argument is not present, but this is not an error -> false, NOT_PRESENT, "" + else return ErrorOr(false, ErrorCodes::NOT_PRESENT, std::string("")); + } + + ErrorOr ArgumentsParser::getUnpositionalArgument(int argc, char* argv[], std::string longName) { + if (!this->argumentsByLongName.contains(longName)) return ErrorOr(true, ErrorCodes::UNKNOWN_KEY, std::string("")); + if (this-wrongUsage) { + if (this->argumentsByLongName[longName]->present) return ErrorOr(true, ErrorCodes::WRONG_USAGE, this->argumentsByLongName[longName]->value); + else return ErrorOr(true, ErrorCodes::NOT_PRESENT, std::string("")); + } + if (this->argumentsByLongName[longName]->present) return ErrorOr(this->argumentsByLongName[longName]->value); + // argument is not present, but this is not an error -> false, NOT_PRESENT, "" + else return ErrorOr(false, ErrorCodes::NOT_PRESENT, std::string("")); + } + //std::string ArgumentsParser::getUsage(); } diff --git a/src/lib/cli.h++ b/src/lib/cli.h++ index 9d1a058..01e44ec 100644 --- a/src/lib/cli.h++ +++ b/src/lib/cli.h++ @@ -77,11 +77,11 @@ namespace CLI { ~ArgumentsParser(); ErrorOr getProgramName(); - ErrorOr getFlag(int argc, char* argv, char shortName); - ErrorOr getFlag(int argc, char* argv, std::string longName); - ErrorOr getPositionalArgument(int argc, char* argv, int position); - ErrorOr getUnpositionalArgument(int argc, char* argv, char shortName); - ErrorOr getUnpositionalArgument(int argc, char* argv, std::string longName); + ErrorOr getFlag(int argc, char* argv[], char shortName); + ErrorOr getFlag(int argc, char* argv[], std::string longName); + ErrorOr getPositionalArgument(int argc, char* argv[], std::vector::size_type position); + ErrorOr getUnpositionalArgument(int argc, char* argv[], char shortName); + ErrorOr getUnpositionalArgument(int argc, char* argv[], std::string longName); std::string getUsage(); }; diff --git a/src/lib/error.h++ b/src/lib/error.h++ index e10d808..6364eb1 100644 --- a/src/lib/error.h++ +++ b/src/lib/error.h++ @@ -75,6 +75,9 @@ namespace ErrorCodes { const uint8_t WRONG_USAGE = 4; + // when dealing with maps + const uint8_t UNKNOWN_KEY = 5; + const uint8_t UNIMPLEMENTED = 254; const uint8_t UNKNOWN = 255;