mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-03 22:54:39 +00:00
Fixes Issue #24
This commit is contained in:
parent
2125f34d35
commit
73f6aa7538
@ -217,9 +217,30 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static bool is_integer(const std::string& aValue) {
|
||||
if(aValue.empty() ||
|
||||
((!isdigit(aValue[0])) && (aValue[0] != '-') && (aValue[0] != '+')))
|
||||
return false;
|
||||
char * tPtr;
|
||||
strtol(aValue.c_str(), &tPtr, 10);
|
||||
return (*tPtr == 0);
|
||||
}
|
||||
|
||||
static bool is_float(const std::string& aValue) {
|
||||
std::istringstream tStream(aValue);
|
||||
float tFloat;
|
||||
// noskipws considers leading whitespace invalid
|
||||
tStream >> std::noskipws >> tFloat;
|
||||
// Check the entire string was consumed
|
||||
// and if either failbit or badbit is set
|
||||
return tStream.eof() && !tStream.fail();
|
||||
}
|
||||
|
||||
// If an argument starts with "-" or "--", then it's optional
|
||||
static bool is_optional(const std::string& aName) {
|
||||
return (!aName.empty() && aName[0] == '-');
|
||||
return (!aName.empty() && aName[0] == '-' &&
|
||||
!is_integer(aName) && !is_float(aName));
|
||||
}
|
||||
|
||||
static bool is_positional(const std::string& aName) {
|
||||
@ -464,10 +485,11 @@ class ArgumentParser {
|
||||
*/
|
||||
void parse_args_validate() {
|
||||
// Check if all arguments are parsed
|
||||
std::for_each(std::begin(mArgumentMap), std::end(mArgumentMap), [](const auto& argPair) {
|
||||
const auto& [key, arg] = argPair;
|
||||
arg->validate();
|
||||
});
|
||||
std::for_each(std::begin(mArgumentMap), std::end(mArgumentMap),
|
||||
[](const auto& argPair) {
|
||||
const auto& tArgument = argPair.second;
|
||||
tArgument->validate();
|
||||
});
|
||||
}
|
||||
|
||||
// Used by print_help.
|
||||
@ -475,11 +497,13 @@ class ArgumentParser {
|
||||
if (mArgumentMap.empty())
|
||||
return 0;
|
||||
std::vector<size_t> argumentLengths(mArgumentMap.size());
|
||||
std::transform(std::begin(mArgumentMap), std::end(mArgumentMap), std::begin(argumentLengths), [](const auto& argPair) {
|
||||
const auto& [key, arg] = argPair;
|
||||
return arg->get_arguments_length();
|
||||
});
|
||||
return *std::max_element(std::begin(argumentLengths), std::end(argumentLengths));
|
||||
std::transform(std::begin(mArgumentMap), std::end(mArgumentMap),
|
||||
std::begin(argumentLengths), [](const auto& argPair) {
|
||||
const auto& tArgument = argPair.second;
|
||||
return tArgument->get_arguments_length();
|
||||
});
|
||||
return *std::max_element(std::begin(argumentLengths),
|
||||
std::end(argumentLengths));
|
||||
}
|
||||
|
||||
std::string mProgramName;
|
||||
|
@ -1,6 +1,18 @@
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
project(ARGPARSE)
|
||||
|
||||
if(MSVC)
|
||||
# Force to always compile with W4
|
||||
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
endif()
|
||||
elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
# Update if necessary
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic")
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
@ -22,4 +34,4 @@ set_target_properties(ARGPARSE PROPERTIES OUTPUT_NAME tests)
|
||||
set_property(TARGET ARGPARSE PROPERTY CXX_STANDARD 17)
|
||||
|
||||
# Set ${PROJECT_NAME} as the startup project
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ARGPARSE)
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ARGPARSE)
|
||||
|
@ -9,3 +9,4 @@
|
||||
#include <test_container_arguments.hpp>
|
||||
#include <test_parent_parsers.hpp>
|
||||
#include <test_invalid_arguments.hpp>
|
||||
#include <test_negative_numbers.hpp>
|
||||
|
@ -100,6 +100,9 @@ TEST_CASE("Parse out-of-order compound arguments", "[compound_arguments]") {
|
||||
auto a = program.get<bool>("-a"); // true
|
||||
auto b = program.get<bool>("-b"); // true
|
||||
auto c = program.get<std::vector<float>>("-c"); // {3.14f, 2.718f}
|
||||
REQUIRE(a == true);
|
||||
REQUIRE(b == true);
|
||||
REQUIRE(program["-c"] == std::vector<float>{3.14f, 2.718f});
|
||||
}
|
||||
|
||||
TEST_CASE("Parse out-of-order compound arguments. Second variation", "[compound_arguments]") {
|
||||
@ -127,4 +130,4 @@ TEST_CASE("Parse out-of-order compound arguments. Second variation", "[compound_
|
||||
REQUIRE(a == false);
|
||||
REQUIRE(b == true);
|
||||
REQUIRE(program["-c"] == std::vector<float>{0.0f, 0.0f});
|
||||
}
|
||||
}
|
||||
|
65
test/test_negative_numbers.hpp
Normal file
65
test/test_negative_numbers.hpp
Normal file
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
#include <catch.hpp>
|
||||
#include <argparse.hpp>
|
||||
|
||||
TEST_CASE("Parse negative integer", "[positional_arguments]") {
|
||||
argparse::ArgumentParser program;
|
||||
program.add_argument("--verbose", "-v")
|
||||
.help("enable verbose logging")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
|
||||
program.add_argument("number")
|
||||
.help("Input number")
|
||||
.action([](const std::string& value) { return std::stoi(value); });
|
||||
|
||||
program.parse_args({"./main", "-1"});
|
||||
REQUIRE(program.get<int>("number") == -1);
|
||||
}
|
||||
|
||||
TEST_CASE("Parse negative integers into a vector", "[positional_arguments]") {
|
||||
argparse::ArgumentParser program;
|
||||
program.add_argument("--verbose", "-v")
|
||||
.help("enable verbose logging")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
|
||||
program.add_argument("number")
|
||||
.help("Input number")
|
||||
.nargs(3)
|
||||
.action([](const std::string& value) { return std::stoi(value); });
|
||||
|
||||
program.parse_args({"./main", "-1", "-2", "3"});
|
||||
REQUIRE(program["number"] == std::vector<int>{-1, -2, 3});
|
||||
}
|
||||
|
||||
TEST_CASE("Parse negative float", "[positional_arguments]") {
|
||||
argparse::ArgumentParser program;
|
||||
program.add_argument("--verbose", "-v")
|
||||
.help("enable verbose logging")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
|
||||
program.add_argument("number")
|
||||
.help("Input number")
|
||||
.action([](const std::string& value) { return std::stof(value); });
|
||||
|
||||
program.parse_args({"./main", "-1.0"});
|
||||
REQUIRE(program.get<float>("number") == -1.0);
|
||||
}
|
||||
|
||||
TEST_CASE("Parse negative floats into a vector", "[positional_arguments]") {
|
||||
argparse::ArgumentParser program;
|
||||
program.add_argument("--verbose", "-v")
|
||||
.help("enable verbose logging")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
|
||||
program.add_argument("number")
|
||||
.help("Input number")
|
||||
.nargs(3)
|
||||
.action([](const std::string& value) { return std::stod(value); });
|
||||
|
||||
program.parse_args({"./main", "-1.001", "-2.002", "3.003"});
|
||||
REQUIRE(program["number"] == std::vector<double>{-1.001, -2.002, 3.003});
|
||||
}
|
Loading…
Reference in New Issue
Block a user