Add command line flag processing.
This commit is contained in:
parent
e80f597ec8
commit
4d2abcf434
2
Arena.cc
2
Arena.cc
|
@ -346,7 +346,7 @@ uint8_t &
|
||||||
Arena::operator[](size_t index)
|
Arena::operator[](size_t index)
|
||||||
{
|
{
|
||||||
if (index > this->size) {
|
if (index > this->size) {
|
||||||
#if defined(SCSL_DESKTOP_BUILD) and !defined(SCSL_NO_ASSERT)
|
#if defined(SCSL_DESKTOP_BUILD) and !defined(SCSL_NOEXCEPT)
|
||||||
throw std::range_error("index out of range");
|
throw std::range_error("index out of range");
|
||||||
#else
|
#else
|
||||||
abort();
|
abort();
|
||||||
|
|
|
@ -330,7 +330,7 @@ uint8_t &
|
||||||
Buffer::operator[](size_t index)
|
Buffer::operator[](size_t index)
|
||||||
{
|
{
|
||||||
if (index > this->length) {
|
if (index > this->length) {
|
||||||
#if defined(SCSL_DESKTOP_BUILD) and !defined(SCSL_NO_ASSERT)
|
#if defined(SCSL_DESKTOP_BUILD) and !defined(SCSL_NOEXCEPT)
|
||||||
throw std::range_error("array index out of bounds");
|
throw std::range_error("array index out of bounds");
|
||||||
#else
|
#else
|
||||||
abort();
|
abort();
|
||||||
|
|
|
@ -5,6 +5,7 @@ if (${DOXYGEN_FOUND})
|
||||||
set(DOXYGEN_GENERATE_MAN YES)
|
set(DOXYGEN_GENERATE_MAN YES)
|
||||||
set(DOXYGEN_GENERATE_LATEX YES)
|
set(DOXYGEN_GENERATE_LATEX YES)
|
||||||
#set(DOXYGEN_EXTRACT_ALL YES)
|
#set(DOXYGEN_EXTRACT_ALL YES)
|
||||||
|
message(STATUS "Doxygen found, building docs.")
|
||||||
|
|
||||||
doxygen_add_docs(scsl_docs
|
doxygen_add_docs(scsl_docs
|
||||||
${HEADER_FILES} ${SOURCE_FILES}
|
${HEADER_FILES} ${SOURCE_FILES}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.22)
|
||||||
project(scsl LANGUAGES CXX
|
project(scsl LANGUAGES CXX
|
||||||
VERSION 0.1.0
|
VERSION 0.1.1
|
||||||
DESCRIPTION "Shimmering Clarity Standard Library")
|
DESCRIPTION "Shimmering Clarity Standard Library")
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
|
@ -33,6 +33,7 @@ set(HEADER_FILES scsl.h
|
||||||
Buffer.h
|
Buffer.h
|
||||||
Dictionary.h
|
Dictionary.h
|
||||||
Exceptions.h
|
Exceptions.h
|
||||||
|
Flag.h
|
||||||
StringUtil.h
|
StringUtil.h
|
||||||
TLV.h
|
TLV.h
|
||||||
Test.h
|
Test.h
|
||||||
|
@ -45,6 +46,7 @@ set(SOURCE_FILES
|
||||||
Commander.h
|
Commander.h
|
||||||
Dictionary.cc
|
Dictionary.cc
|
||||||
Exceptions.cc
|
Exceptions.cc
|
||||||
|
Flag.cc
|
||||||
StringUtil.cc
|
StringUtil.cc
|
||||||
TLV.cc
|
TLV.cc
|
||||||
Test.cc
|
Test.cc
|
||||||
|
@ -66,6 +68,10 @@ target_link_libraries(phonebook scsl)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
|
add_executable(buffer_test bufferTest.cc)
|
||||||
|
target_link_libraries(buffer_test scsl)
|
||||||
|
add_test(bufferTest buffer_test)
|
||||||
|
|
||||||
add_executable(tlv_test tlvTest.cc)
|
add_executable(tlv_test tlvTest.cc)
|
||||||
target_link_libraries(tlv_test scsl)
|
target_link_libraries(tlv_test scsl)
|
||||||
add_test(tlvTest tlv_test)
|
add_test(tlvTest tlv_test)
|
||||||
|
@ -74,9 +80,9 @@ add_executable(dictionary_test dictionaryTest.cc)
|
||||||
target_link_libraries(dictionary_test scsl)
|
target_link_libraries(dictionary_test scsl)
|
||||||
add_test(dictionaryTest dictionary_test)
|
add_test(dictionaryTest dictionary_test)
|
||||||
|
|
||||||
add_executable(buffer_test bufferTest.cc)
|
add_executable(flag_test flagTest.cc)
|
||||||
target_link_libraries(buffer_test scsl)
|
target_link_libraries(flag_test scsl)
|
||||||
add_test(bufferTest buffer_test)
|
add_test(flagTest flag_test)
|
||||||
|
|
||||||
add_executable(stringutil_test stringutil_test.cc)
|
add_executable(stringutil_test stringutil_test.cc)
|
||||||
target_link_libraries(stringutil_test scsl)
|
target_link_libraries(stringutil_test scsl)
|
||||||
|
@ -94,7 +100,7 @@ add_custom_target(cloc
|
||||||
COMMAND cloc ${SOURCE_FILES} ${HEADER_FILES}
|
COMMAND cloc ${SOURCE_FILES} ${HEADER_FILES}
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
||||||
add_custom_target(deploy-docs
|
add_custom_target(deploy-docs
|
||||||
COMMAND rsync --progress -auvz ${CMAKE_CURRENT_BINARY_DIR}/html/* docs.shimmering-clarity.net:sites/cc/
|
COMMAND rsync --delete-after --progress -auvz ${CMAKE_CURRENT_BINARY_DIR}/html/* docs.shimmering-clarity.net:sites/cc/${PROJECT_NAME}/
|
||||||
DEPENDS scsl_docs
|
DEPENDS scsl_docs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
235
Flag.cc
235
Flag.cc
|
@ -30,18 +30,45 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Flag.h"
|
#include "Flag.h"
|
||||||
|
#include "StringUtil.h"
|
||||||
|
|
||||||
|
|
||||||
namespace klib {
|
namespace scsl {
|
||||||
|
|
||||||
|
|
||||||
static const std::regex isFlag("^-[a-zA-Z0-9]+$",
|
static const std::regex isFlag("^--?[a-zA-Z0-9][a-zA-Z0-9-_]*$",
|
||||||
std::regex_constants::nosubs);
|
std::regex_constants::nosubs);
|
||||||
|
|
||||||
|
std::string
|
||||||
Flag::Flag(FlagType fType, std::string fName, std::string fDescription)
|
ParseStatusToString(ParseStatus status)
|
||||||
: Type(fType), WasSet(false), Name(fName), Description(fDescription)
|
|
||||||
{
|
{
|
||||||
|
switch (status) {
|
||||||
|
case ParseStatus::OK:
|
||||||
|
return "OK";
|
||||||
|
case ParseStatus::EndOfFlags:
|
||||||
|
return "end of flags";
|
||||||
|
case ParseStatus::NotRegistered:
|
||||||
|
return "flag not registered";
|
||||||
|
case ParseStatus::NotEnoughArgs:
|
||||||
|
return "not enough args passed to flags";
|
||||||
|
default:
|
||||||
|
return "unknown/unspecified parse error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Flag *
|
||||||
|
NewFlag(FlagType fType, std::string fName, std::string fDescription)
|
||||||
|
{
|
||||||
|
auto flag = new Flag;
|
||||||
|
|
||||||
|
flag->Type = fType;
|
||||||
|
flag->WasSet = false;
|
||||||
|
flag->Name = fName;
|
||||||
|
flag->Description = fDescription;
|
||||||
|
flag->Value = FlagValue{};
|
||||||
|
|
||||||
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,16 +95,79 @@ Flags::Register(std::string fName, FlagType fType, std::string fDescription)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto flag = new Flag;
|
auto flag = NewFlag(fType, fName, fDescription);
|
||||||
flag->Type = fType;
|
|
||||||
flag->WasSet = false;
|
|
||||||
flag->name = name;
|
|
||||||
this->desription = fDescription;
|
|
||||||
this->flags[fName] = flag;
|
this->flags[fName] = flag;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Flags::Register(std::string fName, bool defaultValue, std::string fDescription)
|
||||||
|
{
|
||||||
|
if (!this->Register(fName, FlagType::Boolean, fDescription)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->flags[fName]->Value.b = defaultValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Flags::Register(std::string fName, int defaultValue, std::string fDescription)
|
||||||
|
{
|
||||||
|
if (!this->Register(fName, FlagType::Integer, fDescription)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->flags[fName]->Value.i = defaultValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Flags::Register(std::string fName, unsigned int defaultValue, std::string fDescription)
|
||||||
|
{
|
||||||
|
if (!this->Register(fName, FlagType::UnsignedInteger, fDescription)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->flags[fName]->Value.u = defaultValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Flags::Register(std::string fName, size_t defaultValue, std::string fDescription)
|
||||||
|
{
|
||||||
|
if (!this->Register(fName, FlagType::SizeT, fDescription)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->flags[fName]->Value.size = defaultValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Flags::Register(std::string fName, std::string defaultValue, std::string fDescription)
|
||||||
|
{
|
||||||
|
if (!this->Register(fName, FlagType::String, fDescription)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->flags[fName]->Value.s = new std::string(defaultValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t
|
||||||
|
Flags::Size()
|
||||||
|
{
|
||||||
|
return this->flags.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Flag *
|
Flag *
|
||||||
Flags::Lookup(std::string fName)
|
Flags::Lookup(std::string fName)
|
||||||
{
|
{
|
||||||
|
@ -85,18 +175,19 @@ Flags::Lookup(std::string fName)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this->flags[fName];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
OptFlagValue
|
bool
|
||||||
Flags::ValueOf(std::string fName)
|
Flags::ValueOf(std::string fName, FlagValue &value)
|
||||||
{
|
{
|
||||||
if (this->flags.count(fName)) {
|
if (this->flags.count(fName)) {
|
||||||
return std::nullopt;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OptFlagValue(this->flags[fName]->Value);
|
value = this->flags[fName]->Value;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,6 +197,8 @@ Flags::parseArg(int argc, char **argv, int &index)
|
||||||
{
|
{
|
||||||
std::string arg(argv[index]);
|
std::string arg(argv[index]);
|
||||||
|
|
||||||
|
U::S::TrimWhitespace(arg);
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
if (!std::regex_search(arg, isFlag)) {
|
if (!std::regex_search(arg, isFlag)) {
|
||||||
return ParseStatus::EndOfFlags;
|
return ParseStatus::EndOfFlags;
|
||||||
|
@ -116,15 +209,33 @@ Flags::parseArg(int argc, char **argv, int &index)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto flag = flags[arg];
|
auto flag = flags[arg];
|
||||||
if (flag->Type == FlagType::Boolean) {
|
switch (flag->Type) {
|
||||||
|
case FlagType::Boolean:
|
||||||
flag->WasSet = true;
|
flag->WasSet = true;
|
||||||
flag->Value.b = true;
|
flag->Value.b = true;
|
||||||
return ParseStatus::OK;
|
return ParseStatus::OK;
|
||||||
}
|
case FlagType::Integer:
|
||||||
|
flag->WasSet = true;
|
||||||
switch (flag->Type) {
|
flag->Value.i = std::stoi(argv[++index], 0, 0);
|
||||||
|
return ParseStatus::OK;
|
||||||
|
case FlagType::UnsignedInteger:
|
||||||
|
flag->WasSet = true;
|
||||||
|
flag->Value.u = static_cast<unsigned int>(std::stoi(argv[index++], 0, 0));
|
||||||
|
return ParseStatus::OK;
|
||||||
|
case FlagType::String:
|
||||||
|
flag->WasSet = true;
|
||||||
|
flag->Value.s = new std::string(argv[index++]);
|
||||||
|
return ParseStatus::OK;
|
||||||
|
case FlagType::SizeT:
|
||||||
|
flag->WasSet = true;
|
||||||
|
flag->Value.size = static_cast<size_t>(std::stoull(argv[index++]));
|
||||||
|
return ParseStatus::OK;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("not handled");
|
#if defined(NDEBUG) or defined(SCSL_NOEXCEPT)
|
||||||
|
return ParseStatus::Unknown;
|
||||||
|
#else
|
||||||
|
throw std::runtime_error("unhandled type");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParseStatus::OK;
|
return ParseStatus::OK;
|
||||||
|
@ -148,12 +259,16 @@ Flags::Parse(int argc, char **argv)
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
case ParseStatus::EndOfFlags:
|
|
||||||
case ParseStatus::NotEnoughArgs:
|
case ParseStatus::NotEnoughArgs:
|
||||||
|
case ParseStatus::NotRegistered:
|
||||||
// fall through //
|
// fall through //
|
||||||
return result;
|
return result;
|
||||||
default:
|
default:
|
||||||
throw runtime_error("unhandled parse state");
|
#if defined(NDEBUG) or defined(SCSL_NOEXCEPT)
|
||||||
|
return ParseStatus::Unknown;
|
||||||
|
#else
|
||||||
|
throw std::runtime_error("unhandled parse state");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -176,16 +291,80 @@ Flags::Args()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
Flag *
|
||||||
Flags::GetBool(std::string name, bool &flagValue)
|
Flags::checkGetArg(std::string fName, FlagType eType)
|
||||||
{
|
{
|
||||||
if (this->flags[name] == 0) {
|
if (this->flags[fName] == 0) {
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::get<bool>(this->flags[name]->Value);
|
auto flag = this->flags[fName];
|
||||||
|
if (flag == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag->Type != eType) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace klib
|
bool
|
||||||
|
Flags::GetBool(std::string fName, bool &flagValue)
|
||||||
|
{
|
||||||
|
auto flag = this->checkGetArg(fName, FlagType::Boolean);
|
||||||
|
|
||||||
|
flagValue = flag->Value.b;
|
||||||
|
return flag->WasSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Flags::GetInteger(std::string fName, int &flagValue)
|
||||||
|
{
|
||||||
|
auto flag = this->checkGetArg(fName, FlagType::Integer);
|
||||||
|
|
||||||
|
flagValue = flag->Value.i;
|
||||||
|
return flag->WasSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Flags::GetUnsignedInteger(std::string fName, unsigned int &flagValue)
|
||||||
|
{
|
||||||
|
auto flag = this->checkGetArg(fName, FlagType::UnsignedInteger);
|
||||||
|
|
||||||
|
flagValue = flag->Value.u;
|
||||||
|
return flag->WasSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Flags::GetSizeT(std::string fName, std::size_t &flagValue)
|
||||||
|
{
|
||||||
|
auto flag = this->checkGetArg(fName, FlagType::SizeT);
|
||||||
|
|
||||||
|
flagValue = flag->Value.size;
|
||||||
|
return flag->WasSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Flags::GetString(std::string fName, std::string &flagValue)
|
||||||
|
{
|
||||||
|
auto flag = this->checkGetArg(fName, FlagType::String);
|
||||||
|
|
||||||
|
if (flag->Value.s == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
flagValue = *(flag->Value.s);
|
||||||
|
return flag->WasSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace scsl
|
||||||
|
|
||||||
|
|
121
Flag.h
121
Flag.h
|
@ -26,49 +26,56 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <optional>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace klib {
|
namespace scsl {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// FlagType indicates the value held in a FlagValue.
|
||||||
enum class FlagType : uint8_t {
|
enum class FlagType : uint8_t {
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
Boolean = 1,
|
Boolean = 1,
|
||||||
Integer = 2,
|
Integer = 2, ///< int32_t
|
||||||
UnsignedInteger = 3,
|
UnsignedInteger = 3, ///< uint32_t
|
||||||
String = 4,
|
SizeT = 4, ///< size_t
|
||||||
|
String = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum class ParseStatus : uint8_t {
|
enum class ParseStatus : uint8_t {
|
||||||
OK = 0,
|
Unknown = 0,
|
||||||
EndOfFlags = 1,
|
OK = 1,
|
||||||
NotRegistered = 2,
|
EndOfFlags = 2,
|
||||||
NotEnoughArgs = 3,
|
NotRegistered = 3,
|
||||||
|
NotEnoughArgs = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string
|
||||||
typedef std::variant<
|
ParseStatusToString(ParseStatus status);
|
||||||
std::string *,
|
|
||||||
bool *,
|
|
||||||
int64_t *,
|
|
||||||
uint64_t *> FlagValue;
|
|
||||||
|
|
||||||
|
|
||||||
struct Flag {
|
typedef union {
|
||||||
Flag(FlagType fType, std::string fName, std::string fDescription);
|
unsigned int u;
|
||||||
|
int i;
|
||||||
|
std::size_t size;
|
||||||
|
std::string *s;
|
||||||
|
bool b;
|
||||||
|
} FlagValue;
|
||||||
|
|
||||||
FlagType Type;
|
|
||||||
bool WasSet;
|
typedef struct {
|
||||||
std::string Name;
|
FlagType Type;
|
||||||
std::string Description;
|
bool WasSet;
|
||||||
FlagValue Value;
|
std::string Name;
|
||||||
};
|
std::string Description;
|
||||||
typedef std::optional<FlagValue> OptFlagValue;
|
FlagValue Value;
|
||||||
|
} Flag;
|
||||||
|
|
||||||
|
Flag *
|
||||||
|
NewFlag(FlagType fType, std::string fName, std::string fDescription);
|
||||||
|
|
||||||
|
|
||||||
class Flags {
|
class Flags {
|
||||||
|
@ -76,36 +83,52 @@ public:
|
||||||
Flags(std::string fName);
|
Flags(std::string fName);
|
||||||
Flags(std::string fName, std::string fDescription);
|
Flags(std::string fName, std::string fDescription);
|
||||||
|
|
||||||
bool Register(std::string fName,
|
bool Register(std::string fName,
|
||||||
FlagType fType,
|
FlagType fType,
|
||||||
std::string fDescription);
|
std::string fDescription);
|
||||||
Flag *Lookup(std::string fName);
|
bool Register(std::string fName,
|
||||||
OptFlagValue
|
bool defaultValue,
|
||||||
ValueOf(std::string fName);
|
std::string fDescription);
|
||||||
|
bool Register(std::string fName,
|
||||||
|
int defaultValue,
|
||||||
|
std::string fDescription);
|
||||||
|
bool Register(std::string fName,
|
||||||
|
unsigned int defaultValue,
|
||||||
|
std::string fDescription);
|
||||||
|
bool Register(std::string fName,
|
||||||
|
size_t defaultValue,
|
||||||
|
std::string fDescription);
|
||||||
|
bool Register(std::string fName,
|
||||||
|
std::string defaultValue,
|
||||||
|
std::string fDescription);
|
||||||
|
size_t Size();
|
||||||
|
Flag *Lookup(std::string fName);
|
||||||
|
bool ValueOf(std::string fName, FlagValue &value);
|
||||||
|
|
||||||
int Parse(int argc, char **argv);
|
ParseStatus Parse(int argc, char **argv);
|
||||||
|
|
||||||
void Usage(std::ostream &os, int exitCode);
|
void Usage(std::ostream &os, int exitCode);
|
||||||
|
|
||||||
size_t NumArgs();
|
size_t NumArgs();
|
||||||
std::vector<std::string> Args();
|
std::vector<std::string> Args();
|
||||||
std::string Arg(int index);
|
std::string Arg(int index);
|
||||||
|
|
||||||
bool GetBool(std::string name, bool &flagValue);
|
bool GetBool(std::string fName, bool &flagValue);
|
||||||
// bool GetUnsignedInteger(std::string name, uint64_t &flagValue)
|
bool GetUnsignedInteger(std::string fName, unsigned int &flagValue);
|
||||||
// bool GetInteger(std::string name, int64_t &flagValue)
|
bool GetInteger(std::string fName, int &flagValue);
|
||||||
// bool GetString(std::string name, std::string &flagValue)
|
bool GetString(std::string fName, std::string &flagValue);
|
||||||
|
bool GetSizeT(std::string fName, std::size_t &flagValue);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ParseStatus parseArg(int argc, char **argv, int &index);
|
ParseStatus parseArg(int argc, char **argv, int &index);
|
||||||
|
Flag *checkGetArg(std::string fName, FlagType eType);
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string description;
|
std::string description;
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
std::map<std::string, Flag *> flags;
|
std::map<std::string, Flag *> flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace scsl
|
||||||
} // namespace klib
|
|
||||||
|
|
4
Test.cc
4
Test.cc
|
@ -15,7 +15,7 @@ namespace scsl {
|
||||||
void
|
void
|
||||||
TestAssert(bool condition, std::string message)
|
TestAssert(bool condition, std::string message)
|
||||||
{
|
{
|
||||||
#if defined(NDEBUG) || defined(SCSL_NO_ASSERT)
|
#if defined(NDEBUG) || defined(SCSL_NOEXCEPT)
|
||||||
if (!condition) {
|
if (!condition) {
|
||||||
throw AssertionFailed(message);
|
throw AssertionFailed(message);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ TestAssert(bool condition)
|
||||||
if (condition) {
|
if (condition) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if defined(SCSL_NO_ASSERT)
|
#if defined(SCSL_NOEXCEPT)
|
||||||
std::cerr << "Assertion failed!\n";
|
std::cerr << "Assertion failed!\n";
|
||||||
#else
|
#else
|
||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
|
|
2
Test.h
2
Test.h
|
@ -29,7 +29,7 @@ void TestAssert(bool condition);
|
||||||
/// If NDEBUG is set, TestAssert will throw an exception if condition is false.
|
/// If NDEBUG is set, TestAssert will throw an exception if condition is false.
|
||||||
/// Otherwise, it calls assert after printing the message.
|
/// Otherwise, it calls assert after printing the message.
|
||||||
///
|
///
|
||||||
/// In addition to NDEBUG, SCSL_NO_ASSERT will suppress assertions.
|
/// In addition to NDEBUG, SCSL_NOEXCEPT will suppress assertions.
|
||||||
///
|
///
|
||||||
/// \throws AssertionFailed
|
/// \throws AssertionFailed
|
||||||
///
|
///
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
//
|
||||||
|
// Created by kyle on 10/15/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "Flag.h"
|
||||||
|
#include "Test.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace scsl;
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
bool testFlag = false;
|
||||||
|
size_t testSize = 0;
|
||||||
|
unsigned int testUnsigned = 0;
|
||||||
|
int testInteger = 0;
|
||||||
|
std::string testString;
|
||||||
|
|
||||||
|
auto flags = new Flags("flag_test", "this is a test of the flag functionality.");
|
||||||
|
flags->Register("-b", FlagType::Boolean, "test boolean");
|
||||||
|
flags->Register("-s", FlagType::String, "test string");
|
||||||
|
flags->Register("-u", (unsigned int)42, "test unsigned integer");
|
||||||
|
flags->Register("-i", -42, "test integer");
|
||||||
|
flags->Register("-size", FlagType::SizeT, "test size_t");
|
||||||
|
TestAssert(flags->Size() == 5, "flags weren't registered");
|
||||||
|
|
||||||
|
auto status = flags->Parse(argc, argv);
|
||||||
|
|
||||||
|
if (status != ParseStatus::OK) {
|
||||||
|
std::cerr << "failed to parse flags: " << ParseStatusToString(status) << "\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto wasSet = flags->GetBool("-b", testFlag);
|
||||||
|
std::cout << " (bool) test flag was set: " << wasSet << "\n";
|
||||||
|
std::cout << " (bool) test flag value: " << testFlag << "\n";
|
||||||
|
|
||||||
|
wasSet = flags->GetInteger("-i", testInteger);
|
||||||
|
std::cout << " (int) test flag was set: " << wasSet << "\n";
|
||||||
|
std::cout << " (int) test flag value: " << testInteger << "\n";
|
||||||
|
|
||||||
|
wasSet = flags->GetUnsignedInteger("-u", testUnsigned);
|
||||||
|
std::cout << " (uint) test flag was set: " << wasSet << "\n";
|
||||||
|
std::cout << " (uint) test flag value: " << testUnsigned << "\n";
|
||||||
|
|
||||||
|
wasSet = flags->GetSizeT("-size", testSize);
|
||||||
|
std::cout << "(size_t) test flag was set: " << wasSet << "\n";
|
||||||
|
std::cout << "(size_t) test flag value: " << testSize << "\n";
|
||||||
|
|
||||||
|
wasSet = flags->GetString("-s", testString);
|
||||||
|
std::cout << "(string) test flag was set: " << wasSet << "\n";
|
||||||
|
std::cout << "(string) test flag value: " << testString << "\n";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue