Skip to content

Commit

Permalink
options: Modernize API for C++17
Browse files Browse the repository at this point in the history
  • Loading branch information
mwestphal committed Jan 2, 2025
1 parent c2529be commit 46d7334
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 55 deletions.
30 changes: 15 additions & 15 deletions library/private/options_tools.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -274,37 +274,37 @@ std::string format(const std::vector<double>& var)
/**
* Generated method, see `options::set`
*/
void set(options& opt, const std::string& name, const option_variant_t& value)
void set(options& opt, std::string_view name, const option_variant_t& value)
{
try
{
// clang-format off
${_options_setter};
// clang-format on
else throw options::inexistent_exception("Option " + name + " does not exist");
else throw options::inexistent_exception("Option " + std::string(name) + " does not exist");
}
catch (const std::bad_variant_access&)
{
throw options::incompatible_exception("Trying to set " + name + " with incompatible type");
throw options::incompatible_exception("Trying to set " + std::string(name) + " with incompatible type");
}
}

//----------------------------------------------------------------------------
/**
* Generated method, see `options::get`
*/
option_variant_t get(const options& opt, const std::string& name)
option_variant_t get(const options& opt, std::string_view name)
{
try
{
// clang-format off
${_options_getter};
// clang-format on
else throw options::inexistent_exception("Option " + name + " does not exist");
else throw options::inexistent_exception("Option " + std::string(name) + " does not exist");
}
catch (const std::bad_optional_access&)
{
throw options::no_value_exception("Trying to get " + name + " before it was set");
throw options::no_value_exception("Trying to get " + std::string(name) + " before it was set");
}
}

Expand All @@ -323,54 +323,54 @@ std::vector<std::string> getNames()
/**
* Generated method, see `options::setAsString`
*/
void setAsString(options& opt, const std::string& name, const std::string& str)
void setAsString(options& opt, std::string_view name, const std::string& str)
{
// clang-format off
${_options_string_setter};
// clang-format on
else throw options::inexistent_exception("Option " + name + " does not exist");
else throw options::inexistent_exception("Option " + std::string(name) + " does not exist");
}
//----------------------------------------------------------------------------
/**
* Generated method, see `options::getAsString`
*/
std::string getAsString(const options& opt, const std::string& name)
std::string getAsString(const options& opt, std::string_view name)
{
try
{
// clang-format off
${_options_string_getter};
// clang-format on
else throw options::inexistent_exception("Option " + name + " does not exist");
else throw options::inexistent_exception("Option " + std::string(name) + " does not exist");
}
catch (const std::bad_optional_access&)
{
throw options::no_value_exception("Trying to get " + name + " before it was set");
throw options::no_value_exception("Trying to get " + std::string(name) + " before it was set");
}
}

//----------------------------------------------------------------------------
/**
* Generated method, see `options::isOptional`
*/
bool isOptional(const std::string& name)
bool isOptional(std::string_view name)
{
// clang-format off
${_options_is_optional};
// clang-format on
else throw options::inexistent_exception("Option " + name + " does not exist");
else throw options::inexistent_exception("Option " + std::string(name) + " does not exist");
}

//----------------------------------------------------------------------------
/**
* Generated method, see `options::reset`
*/
void reset(options& opt, const std::string& name)
void reset(options& opt, std::string_view name)
{
// clang-format off
${_options_reset};
// clang-format on
else throw options::inexistent_exception("Option " + name + " does not exist");
else throw options::inexistent_exception("Option " + std::string(name) + " does not exist");
}

} // option_tools
Expand Down
38 changes: 14 additions & 24 deletions library/public/options.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ public:
* Throw an options::inexistent_exception if option does not exist.
* Throw an options::incompatible_exception if value is not compatible with option.
*/
options& set(const std::string& name, const option_variant_t& value);
options& set(std::string_view name, const option_variant_t& value);

/**
* Get an option as a variant based on its name
* Throw an options::inexistent_exception if option does not exist.
* Throw an options::no_value_exception if option has not been set.
*/
[[nodiscard]] option_variant_t get(const std::string& name) const;
[[nodiscard]] option_variant_t get(std::string_view name) const;

/**
* Set an option as a string based on its name
Expand All @@ -62,42 +62,42 @@ public:
* Throw an options::inexistent_exception if option does not exist.
* Throw an options::parsing_exception if parsing failed.
*/
options& setAsString(const std::string& name, const std::string& str);
options& setAsString(std::string_view name, const std::string& str);

/**
* Get an option as a string based on its name
* Throw an options::inexistent_exception if option does not exist.
* Throw an options::no_value_exception if option has not been set.
*/
[[nodiscard]] std::string getAsString(const std::string& name) const;
[[nodiscard]] std::string getAsString(std::string_view name) const;

/**
* A boolean option specific method to toggle it.
* If the option has not been set yet, set it to true.
* Throw an options::inexistent_exception if option does not exist.
* Throw an options::incompatible_exception if option is not boolean.
*/
options& toggle(const std::string& name);
options& toggle(std::string_view name);

/**
* Compare an option between this and a provided other.
* Return true if they are the same value, false otherwise.
* Throw an options::inexistent_exception if option does not exist.
*/
[[nodiscard]] bool isSame(const options& other, const std::string& name) const;
[[nodiscard]] bool isSame(const options& other, std::string_view name) const;

/**
* Return true if an option has a value, false otherwise
* Always returns true for non-optional options.
* Throw an options::inexistent_exception if option does not exist.
*/
[[nodiscard]] bool hasValue(const std::string& name) const;
[[nodiscard]] bool hasValue(std::string_view name) const;

/**
* Copy the value of an option from this to the provided other.
* Throw an options::inexistent_exception if option does not exist.
*/
options& copy(const options& other, const std::string& name);
options& copy(const options& other, std::string_view name);

/**
* Get all available option names.
Expand All @@ -113,40 +113,30 @@ public:
* Get the closest option name and its Levenshtein distance.
*/
[[nodiscard]] std::pair<std::string, unsigned int> getClosestOption(
const std::string& option) const;
std::string_view option) const;

/**
* Returns true if the option is optional else returns false.
* Throws an options::inexistent_exception if option does not exist.
*/
[[nodiscard]] bool isOptional(const std::string& option) const;
[[nodiscard]] bool isOptional(std::string_view option) const;

/**
* Resets the option to default value.
* Throws an options::inexistent_exception if option does not exist.
*/
options& reset(const std::string& name);
options& reset(std::string_view name);

/**
* Unset the option if it is optional else throws options::incompatible_exception.
* Throws an options::inexistent_exception if option does not exist.
*/
options& removeValue(const std::string& name);
options& removeValue(std::string_view name);

/**
* Templated parsing method used internally to parse strings.
* Implemented for:
* - `bool` as `"true"`/`"false"`, `"1"`/`"0"`, `"yes"`/`"no"`, `"on"`/`"off"`
* (case-insensitive)
* - `int`: `"123"`, `"+123"`, `"-456"`
* - `double`: `"123.45"`, `"+123.45"`, `"-67.8"`, `"-1e3"`
* - `ratio_t`: as
* + a number, same a `double` above
* + a percentage: `"12.3%"` => `0.123`
* + a fraction: `"3/4"` => `0.75`
* - `vector<T>` where `T` is one of the above: the input is split on `","` and chunks are trimmed
* before parsing each element.
* See parsing documentation for more info. TODO.
* Implemented for the different supported types,
* see PARSING.md for more info.
* Throw an options::parsing_exception if parsing failed.
*/
template<typename T>
Expand Down
32 changes: 16 additions & 16 deletions library/src/options.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,33 @@ options::options()
};

//----------------------------------------------------------------------------
options& options::set(const std::string& name, const option_variant_t& value)
options& options::set(std::string_view name, const option_variant_t& value)
{
options_tools::set(*this, name, value);
return *this;
}

//----------------------------------------------------------------------------
option_variant_t options::get(const std::string& name) const
option_variant_t options::get(std::string_view name) const
{
return options_tools::get(*this, name);
}

//----------------------------------------------------------------------------
options& options::setAsString(const std::string& name, const std::string& str)
options& options::setAsString(std::string_view name, const std::string& str)
{
options_tools::setAsString(*this, name, str);
return *this;
}

//----------------------------------------------------------------------------
std::string options::getAsString(const std::string& name) const
std::string options::getAsString(std::string_view name) const
{
return options_tools::getAsString(*this, name);
}

//----------------------------------------------------------------------------
options& options::toggle(const std::string& name)
options& options::toggle(std::string_view name)
{
try
{
Expand All @@ -62,12 +62,12 @@ options& options::toggle(const std::string& name)
catch (const std::bad_variant_access&)
{
throw options::incompatible_exception(
"Trying to get toggle " + name + " with incompatible type");
"Trying to get toggle " + std::string(name) + " with incompatible type");
}
}

//----------------------------------------------------------------------------
bool options::isSame(const options& other, const std::string& name) const
bool options::isSame(const options& other, std::string_view name) const
{
try
{
Expand All @@ -80,7 +80,7 @@ bool options::isSame(const options& other, const std::string& name) const
}

//----------------------------------------------------------------------------
bool options::hasValue(const std::string& name) const
bool options::hasValue(std::string_view name) const
{
try
{
Expand All @@ -94,7 +94,7 @@ bool options::hasValue(const std::string& name) const
}

//----------------------------------------------------------------------------
options& options::copy(const options& from, const std::string& name)
options& options::copy(const options& from, std::string_view name)
{
options_tools::set(*this, name, options_tools::get(from, name));
return *this;
Expand All @@ -112,17 +112,17 @@ std::vector<std::string> options::getNames() const
const std::vector<std::string> names = options::getAllNames();
std::vector<std::string> setNames;
std::copy_if(names.begin(), names.end(), std::back_inserter(setNames),
[&](const std::string& name) { return this->hasValue(name); });
[&](std::string_view name) { return this->hasValue(name); });
return setNames;
}

//----------------------------------------------------------------------------
std::pair<std::string, unsigned int> options::getClosestOption(const std::string& option) const
std::pair<std::string, unsigned int> options::getClosestOption(std::string_view option) const
{
std::vector<std::string> names = options_tools::getNames();
if (std::find(names.begin(), names.end(), option) != names.end())
{
return { option, 0 };
return { std::string(option), 0 };
}

std::pair<std::string, int> ret = { "", std::numeric_limits<int>::max() };
Expand All @@ -140,28 +140,28 @@ std::pair<std::string, unsigned int> options::getClosestOption(const std::string
}

//----------------------------------------------------------------------------
bool options::isOptional(const std::string& option) const
bool options::isOptional(std::string_view option) const
{
return options_tools::isOptional(option);
}

//----------------------------------------------------------------------------
options& options::reset(const std::string& name)
options& options::reset(std::string_view name)
{
options_tools::reset(*this, name);
return *this;
}

//----------------------------------------------------------------------------
options& options::removeValue(const std::string& name)
options& options::removeValue(std::string_view name)
{
if (this->isOptional(name))
{
this->reset(name);
}
else
{
throw options::incompatible_exception("Option " + name + " is not not optional");
throw options::incompatible_exception("Option " + std::string(name) + " is not not optional");
}
return *this;
}
Expand Down

0 comments on commit 46d7334

Please sign in to comment.