Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions include/CLI/App.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,8 @@ Option *default_flag_modifiers(Option *opt) {

class Option_group;
/// Creates a command line program, with very few defaults.
/** To use, create a new `Program()` instance with `argc`, `argv`, and a help description. The templated
* add_option methods make it easy to prepare options. Remember to call `.start` before starting your
* program, so that the options can be evaluated and the help option doesn't accidentally run your program. */
/** To use, create a new `App` instance with a description, then call `parse(argc, argv)`. The templated
* add_option methods make it easy to prepare options. After parsing, bound variables hold the parsed values. */
class App {
friend Option;
friend detail::AppFriend;
Expand Down Expand Up @@ -411,7 +410,7 @@ class App {
return this;
}

/// Remove the error when extras are left over on the command line.
/// Set whether this subcommand/option-group is required to be present on the command line.
App *required(bool require = true) {
required_ = require;
return this;
Expand Down
4 changes: 2 additions & 2 deletions include/CLI/ExtraValidators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ inline AsNumberWithUnit::Options operator|(const AsNumberWithUnit::Options &a, c
/// Converts a human-readable size string (with unit literal) to uin64_t size.
/// Example:
/// "100" => 100
/// "1 b" => 100
/// "1 b" => 1
/// "10Kb" => 10240 // you can configure this to be interpreted as kilobyte (*1000) or kibibyte (*1024)
/// "10 KB" => 10240
/// "10 kb" => 10240
Expand Down Expand Up @@ -613,7 +613,7 @@ const detail::PermissionValidator ReadPermissions(detail::Permission::read);
/// Check that the file exist and available for write
const detail::PermissionValidator WritePermissions(detail::Permission::write);

/// Check that the file exist and available for write
/// Check that the file exist and available for execute
const detail::PermissionValidator ExecPermissions(detail::Permission::exec);

/// Check that the file exists and is not empty
Expand Down
8 changes: 4 additions & 4 deletions include/CLI/Validators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,25 +281,25 @@ class Range : public Validator {
/// Check for a non negative number
CLI11_MODULE_INLINE const Range NonNegativeNumber((std::numeric_limits<double>::max)(), "NONNEGATIVE");

/// Check for a positive valued number (val>0.0), <double>::min here is the smallest positive number
/// Check for a positive valued number (val>0.0), <double>::denorm_min is the smallest positive number
CLI11_MODULE_INLINE const
Range PositiveNumber((std::numeric_limits<double>::min)(), (std::numeric_limits<double>::max)(), "POSITIVE");
Range PositiveNumber((std::numeric_limits<double>::denorm_min)(), (std::numeric_limits<double>::max)(), "POSITIVE");

namespace detail {
// the following suggestion was made by Nikita Ofitserov(@himikof)
// done in templates to prevent compiler warnings on negation of unsigned numbers

/// Do a check for overflow on signed numbers
template <typename T>
inline typename std::enable_if<std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
inline typename std::enable_if<std::is_signed<T>::value, bool>::type overflowCheck(const T &a, const T &b) {
if((a > 0) == (b > 0)) {
return ((std::numeric_limits<T>::max)() / (std::abs)(a) < (std::abs)(b));
}
return ((std::numeric_limits<T>::min)() / (std::abs)(a) > -(std::abs)(b));
}
/// Do a check for overflow on unsigned numbers
template <typename T>
inline typename std::enable_if<!std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
inline typename std::enable_if<!std::is_signed<T>::value, bool>::type overflowCheck(const T &a, const T &b) {
return ((std::numeric_limits<T>::max)() / a < b);
}

Expand Down
1 change: 0 additions & 1 deletion include/CLI/impl/Argv_inl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include "../Encoding.hpp"

// [CLI11:public_includes:set]
#include <algorithm>
#include <memory>
#include <stdexcept>
#include <string>
Expand Down
2 changes: 1 addition & 1 deletion include/CLI/impl/Validators_inl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ CLI11_INLINE FileOnDefaultPath::FileOnDefaultPath(std::string default_path, bool
auto path_result = detail::check_path(filename.c_str());
if(path_result == detail::path_type::nonexistent) {
std::string test_file_path = default_path;
if(default_path.back() != '/' && default_path.back() != '\\') {
if(!default_path.empty() && default_path.back() != '/' && default_path.back() != '\\') {
// Add folder separator
test_file_path += '/';
}
Expand Down
9 changes: 9 additions & 0 deletions tests/HelpersTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,12 @@ TEST_CASE("Validators: FilePathModifier", "[helpers]") {
CLI::FileOnDefaultPath defPathNoFail("../", false);
CHECK(defPathNoFail(filename2).empty());
CHECK(filename2 == "nonexistingfile.csv");
// empty default path must not invoke UB via back() on an empty string
CLI::FileOnDefaultPath defPathEmpty("", false);
std::string filename3 = "nonexistingfile.csv";
CHECK(defPathEmpty(filename3).empty());
CLI::FileOnDefaultPath defPathEmptyErr("", true);
CHECK_FALSE(defPathEmptyErr(filename3).empty());
}

TEST_CASE("Validators: FileIsDir", "[helpers]") {
Expand Down Expand Up @@ -647,6 +653,9 @@ TEST_CASE("Validators: PositiveValidator", "[helpers]") {
CHECK_FALSE(CLI::PositiveNumber(num).empty());
num = "a";
CHECK_FALSE(CLI::PositiveNumber(num).empty());
// subnormal positive doubles are strictly positive and must be accepted
num = "5e-324"; // std::numeric_limits<double>::denorm_min
CHECK(CLI::PositiveNumber(num).empty());
}

TEST_CASE("Validators: NonNegativeValidator", "[helpers]") {
Expand Down
Loading