You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

214 lines
10 KiB

#include "src/settings/Option.h"
#include <iomanip>
#include <string>
#include "ArgumentBase.h"
#include "Argument.h"
#include "src/utility/macros.h"
#include "src/exceptions/IllegalArgumentException.h"
#include "src/exceptions/OptionUnificationException.h"
namespace storm {
namespace settings {
Option::Option(std::string const& moduleName, std::string const& longOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments) : Option(moduleName, longOptionName, "", false, optionDescription, isOptionRequired, requireModulePrefix, optionArguments) {
// Intentionally left empty.
}
Option::Option(std::string const& moduleName, std::string const& longOptionName, std::string const& shortOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments) : Option(moduleName, longOptionName, shortOptionName, true, optionDescription, isOptionRequired, requireModulePrefix, optionArguments) {
// Intentionally left empty.
}
bool Option::isCompatibleWith(Option const& other) {
STORM_LOG_THROW(this->getArgumentCount() == other.getArgumentCount(), storm::exceptions::OptionUnificationException, "Unable to unify two options, because their argument count differs.");
for(size_t i = 0; i != this->arguments.size(); i++) {
ArgumentBase const& firstArgument = this->getArgument(i);
ArgumentBase const& secondArgument = other.getArgument(i);
STORM_LOG_THROW(firstArgument.getType() == secondArgument.getType(), storm::exceptions::OptionUnificationException, "Unable to unify two options, because their arguments are incompatible.");
switch (firstArgument.getType()) {
case ArgumentType::String:
static_cast<storm::settings::Argument<std::string> const&>(firstArgument).isCompatibleWith(static_cast<storm::settings::Argument<std::string> const&>(secondArgument));
break;
case ArgumentType::Integer:
static_cast<storm::settings::Argument<int_fast64_t> const&>(firstArgument).isCompatibleWith(static_cast<storm::settings::Argument<int_fast64_t> const&>(secondArgument));
break;
case ArgumentType::UnsignedInteger:
static_cast<storm::settings::Argument<uint_fast64_t> const&>(firstArgument).isCompatibleWith(static_cast<storm::settings::Argument<uint_fast64_t> const&>(secondArgument));
break;
case ArgumentType::Double:
static_cast<storm::settings::Argument<double> const&>(firstArgument).isCompatibleWith(static_cast<storm::settings::Argument<double> const&>(secondArgument));
break;
case ArgumentType::Boolean:
static_cast<storm::settings::Argument<bool> const&>(firstArgument).isCompatibleWith(static_cast<storm::settings::Argument<bool> const&>(secondArgument));
break;
}
}
return true;
}
uint_fast64_t Option::getArgumentCount() const {
return this->arguments.size();
}
ArgumentBase const& Option::getArgument(uint_fast64_t argumentIndex) const {
STORM_LOG_THROW(argumentIndex < this->getArgumentCount(), storm::exceptions::IllegalArgumentException, "Index of argument is out of bounds.");
return *this->arguments.at(argumentIndex);
}
ArgumentBase& Option::getArgument(uint_fast64_t argumentIndex) {
STORM_LOG_THROW(argumentIndex < this->getArgumentCount(), storm::exceptions::IllegalArgumentException, "Index of argument is out of bounds.");
return *this->arguments.at(argumentIndex);
}
ArgumentBase const& Option::getArgumentByName(std::string const& argumentName) const {
auto argumentIterator = this->argumentNameMap.find(argumentName);
STORM_LOG_THROW(argumentIterator != this->argumentNameMap.end(), storm::exceptions::IllegalArgumentException, "Unable to retrieve argument with unknown name '" << argumentName << "'.");
return *argumentIterator->second;
}
std::string const& Option::getLongName() const {
return this->longName;
}
bool Option::getHasShortName() const {
return this->hasShortName;
}
std::string const& Option::getShortName() const {
return this->shortName;
}
std::string const& Option::getDescription() const {
return this->description;
}
std::string const& Option::getModuleName() const {
return this->moduleName;
}
bool Option::getIsRequired() const {
return this->isRequired;
}
bool Option::getRequiresModulePrefix() const {
return this->requireModulePrefix;
}
bool Option::getHasOptionBeenSet() const {
return this->hasBeenSet;
}
Option::Option(std::string const& moduleName, std::string const& longOptionName, std::string const& shortOptionName, bool hasShortOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments) : longName(longOptionName), hasShortName(hasShortOptionName), shortName(shortOptionName), description(optionDescription), moduleName(moduleName), isRequired(isOptionRequired), requireModulePrefix(requireModulePrefix), hasBeenSet(false), arguments(optionArguments), argumentNameMap() {
// First, do some sanity checks.
STORM_LOG_THROW(!longName.empty(), storm::exceptions::IllegalArgumentException, "Unable to construct option with empty name.");
STORM_LOG_THROW(!moduleName.empty(), storm::exceptions::IllegalArgumentException, "Unable to construct option with empty module name.");
bool longNameContainsNonAlpha = std::find_if(longName.begin(), longName.end(), [](char c) { return !(std::isalpha(c) || std::isdigit(c)); }) != longName.end();
STORM_LOG_THROW(!longNameContainsNonAlpha, storm::exceptions::IllegalArgumentException, "Unable to construct option with illegal long name '" << longName << "'.");
bool shortNameContainsNonAlpha = std::find_if(shortName.begin(), shortName.end(), [](char c) { return !(std::isalpha(c) || std::isdigit(c)); }) != shortName.end();
STORM_LOG_THROW(!shortNameContainsNonAlpha, storm::exceptions::IllegalArgumentException, "Unable to construct option with illegal short name '" << shortName << "'.");
// Then index all arguments.
for (auto const& argument : arguments) {
argumentNameMap.emplace(argument->getName(), argument);
}
}
void Option::setHasOptionBeenSet(bool newValue) {
this->hasBeenSet = newValue;
}
uint_fast64_t Option::getPrintLength() const {
uint_fast64_t length = 2;
if (!this->getRequiresModulePrefix()) {
length += 2;
}
length += this->getModuleName().length() + 1;
length += this->getLongName().length();
if (this->getHasShortName()) {
length += 4;
if (!this->getRequiresModulePrefix()) {
length += 2;
}
length += this->getModuleName().length() + 1;
length += this->getShortName().length();
}
return length;
}
std::vector<std::shared_ptr<ArgumentBase>> const& Option::getArguments() const {
return this->arguments;
}
std::ostream& operator<<(std::ostream& out, Option const& option) {
uint_fast64_t width = static_cast<uint_fast64_t>(out.width());
uint_fast64_t charactersPrinted = 0;
out << std::setw(0) << "--";
charactersPrinted += 2;
if (!option.getRequiresModulePrefix()) {
out << "[";
++charactersPrinted;
}
out << option.getModuleName() << ":";
charactersPrinted += option.getModuleName().length() + 1;
if (!option.getRequiresModulePrefix()) {
out << "]";
++charactersPrinted;
}
out << option.getLongName();
charactersPrinted += option.getLongName().length();
if (option.getHasShortName()) {
out << " | -";
charactersPrinted += 4;
if (!option.getRequiresModulePrefix()) {
out << "[";
++charactersPrinted;
}
out << option.getModuleName() << ":";
charactersPrinted += option.getModuleName().length() + 1;
if (!option.getRequiresModulePrefix()) {
out << "]";
++charactersPrinted;
}
out << option.getShortName();
charactersPrinted += option.getShortName().length();
}
// Now fill the width.
for (uint_fast64_t i = charactersPrinted; i < width; ++i) {
out << out.fill();
}
out << "\t" << option.getDescription();
if (option.getArgumentCount() > 0) {
// Start by determining the longest print length of the arguments.
uint_fast64_t maxLength = 0;
for (auto const& argument : option.getArguments()) {
maxLength = std::max(maxLength, argument->getPrintLength());
}
for (auto const& argument : option.getArguments()) {
out << std::endl;
out << "\t* " << std::setw(maxLength) << std::left << *argument;
}
}
return out;
}
}
}