From e80f597ec8dc5e54f4d98ab85cd77ca0ec2d74dc Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Sun, 15 Oct 2023 01:11:06 -0700 Subject: [PATCH] Add Flag files from rcpp branch. This doesn't compile yet, I just need to move them to my main development machine. --- Flag.cc | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Flag.h | 111 ++++++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+) create mode 100644 Flag.cc create mode 100644 Flag.h diff --git a/Flag.cc b/Flag.cc new file mode 100644 index 0000000..96c8499 --- /dev/null +++ b/Flag.cc @@ -0,0 +1,191 @@ +/// +/// \file Flag.h +/// \author kyle +/// \created 2023-10-12 +/// \brief Flag defines a command-line flag parser. +/// +/// \section COPYRIGHT +/// +/// Copyright 2023 K. Isom +/// +/// Permission to use, copy, modify, and/or distribute this software for +/// any purpose with or without fee is hereby granted, provided that +/// the above copyright notice and this permission notice appear in all /// copies. +/// +/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA +/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +/// PERFORMANCE OF THIS SOFTWARE. +/// + + +#include +#include +#include +#include +#include + +#include "Flag.h" + + +namespace klib { + + +static const std::regex isFlag("^-[a-zA-Z0-9]+$", + std::regex_constants::nosubs); + + +Flag::Flag(FlagType fType, std::string fName, std::string fDescription) + : Type(fType), WasSet(false), Name(fName), Description(fDescription) +{ +} + + +Flags::Flags(std::string fName) + : name(fName), description("") +{ +} + + +Flags::Flags(std::string fName, std::string fDescription) + : name(fName), description(fDescription) +{ +} + + +bool +Flags::Register(std::string fName, FlagType fType, std::string fDescription) +{ + if (!std::regex_search(fName, isFlag)) { + return false; + } + + if (this->flags.count(fName) != 0) { + return false; + } + + auto flag = new Flag; + flag->Type = fType; + flag->WasSet = false; + flag->name = name; + this->desription = fDescription; + this->flags[fName] = flag; + return true; +} + + +Flag * +Flags::Lookup(std::string fName) +{ + if (this->flags.count(fName) == 0) { + return nullptr; + } + + +} + + +OptFlagValue +Flags::ValueOf(std::string fName) +{ + if (this->flags.count(fName)) { + return std::nullopt; + } + + return OptFlagValue(this->flags[fName]->Value); +} + + + +ParseStatus +Flags::parseArg(int argc, char **argv, int &index) +{ + std::string arg(argv[index]); + + index++; + if (!std::regex_search(arg, isFlag)) { + return ParseStatus::EndOfFlags; + } + + if (this->flags.count(arg) == 0) { + return ParseStatus::NotRegistered; + } + + auto flag = flags[arg]; + if (flag->Type == FlagType::Boolean) { + flag->WasSet = true; + flag->Value.b = true; + return ParseStatus::OK; + } + + switch (flag->Type) { + default: + throw std::runtime_error("not handled"); + } + + return ParseStatus::OK; +} + + +ParseStatus +Flags::Parse(int argc, char **argv) +{ + int index = 1; + + while (index != argc) { + auto result = this->parseArg(argc, argv, index); + switch (result) { + case ParseStatus::OK: + continue; + + case ParseStatus::EndOfFlags: + while (index < argc) { + this->args.push_back(std::string(argv[index])); + index++; + } + continue; + case ParseStatus::EndOfFlags: + case ParseStatus::NotEnoughArgs: + // fall through // + return result; + default: + throw runtime_error("unhandled parse state"); + } + + } + + return ParseStatus::OK; +} + + +size_t +Flags::NumArgs() +{ + return this->args.size(); +} + + +std::vector +Flags::Args() +{ + return this->args; +} + + +bool +Flags::GetBool(std::string name, bool &flagValue) +{ + if (this->flags[name] == 0) { + return false; + } + + return std::get(this->flags[name]->Value); +} + + +} // namespace klib + diff --git a/Flag.h b/Flag.h new file mode 100644 index 0000000..78ff599 --- /dev/null +++ b/Flag.h @@ -0,0 +1,111 @@ +/// +/// \file Flag.h +/// \author kyle +/// \created 2023-10-12 +/// \brief Flag declares a command-line flag parser. +/// +/// \section COPYRIGHT +/// +/// Copyright 2023 K. Isom +/// +/// Permission to use, copy, modify, and/or distribute this software for +/// any purpose with or without fee is hereby granted, provided that +/// the above copyright notice and this permission notice appear in all /// copies. +/// +/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA +/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +/// PERFORMANCE OF THIS SOFTWARE. +/// + + +#include +#include +#include +#include +#include +#include + + +namespace klib { + + + +enum class FlagType : uint8_t { + Unknown = 0, + Boolean = 1, + Integer = 2, + UnsignedInteger = 3, + String = 4, +}; + + +enum class ParseStatus : uint8_t { + OK = 0, + EndOfFlags = 1, + NotRegistered = 2, + NotEnoughArgs = 3, +}; + + +typedef std::variant< + std::string *, + bool *, + int64_t *, + uint64_t *> FlagValue; + + +struct Flag { + Flag(FlagType fType, std::string fName, std::string fDescription); + + FlagType Type; + bool WasSet; + std::string Name; + std::string Description; + FlagValue Value; +}; +typedef std::optional OptFlagValue; + + +class Flags { +public: + Flags(std::string fName); + Flags(std::string fName, std::string fDescription); + + bool Register(std::string fName, + FlagType fType, + std::string fDescription); + Flag *Lookup(std::string fName); + OptFlagValue + ValueOf(std::string fName); + + int Parse(int argc, char **argv); + + void Usage(std::ostream &os, int exitCode); + + size_t NumArgs(); + std::vector Args(); + std::string Arg(int index); + + bool GetBool(std::string name, bool &flagValue); + // bool GetUnsignedInteger(std::string name, uint64_t &flagValue) + // bool GetInteger(std::string name, int64_t &flagValue) + // bool GetString(std::string name, std::string &flagValue) + + +private: + ParseStatus parseArg(int argc, char **argv, int &index); + + std::string name; + std::string description; + std::vector args; + std::map flags; +}; + + + +} // namespace klib