v2
parent
a437935ab0
commit
457dd5203b
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
include(cmake/color.cmake)
|
include(cmake/color.cmake)
|
||||||
set(BLT_VERSION 4.0.0)
|
set(BLT_VERSION 4.0.1)
|
||||||
|
|
||||||
set(BLT_TARGET BLT)
|
set(BLT_TARGET BLT)
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,10 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <type_traits>
|
||||||
#include <blt/iterator/enumerate.h>
|
#include <blt/iterator/enumerate.h>
|
||||||
|
#include <blt/std/ranges.h>
|
||||||
|
#include <blt/std/utility.h>
|
||||||
|
|
||||||
namespace blt::argparse
|
namespace blt::argparse
|
||||||
{
|
{
|
||||||
|
@ -35,8 +38,10 @@ namespace blt::argparse
|
||||||
inline hashset_t<std::string_view> allowed_flag_prefixes = {"-", "--", "+"};
|
inline hashset_t<std::string_view> allowed_flag_prefixes = {"-", "--", "+"};
|
||||||
|
|
||||||
std::string flag_prefixes_as_string();
|
std::string flag_prefixes_as_string();
|
||||||
|
hashset_t<char> prefix_characters();
|
||||||
|
|
||||||
inline std::string flag_prefix_list_string = flag_prefixes_as_string();
|
inline std::string flag_prefix_list_string = flag_prefixes_as_string();
|
||||||
|
inline auto prefix_characters_set = prefix_characters();
|
||||||
|
|
||||||
class bad_flag final : public std::runtime_error
|
class bad_flag final : public std::runtime_error
|
||||||
{
|
{
|
||||||
|
@ -64,7 +69,42 @@ namespace blt::argparse
|
||||||
using arg_data_t = std::variant<arg_primitive_data_t, arg_list_data_t>;
|
using arg_data_t = std::variant<arg_primitive_data_t, arg_list_data_t>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class arg_type_t;
|
struct arg_type_t
|
||||||
|
{
|
||||||
|
static T convert(const std::string_view value)
|
||||||
|
{
|
||||||
|
const std::string temp{value};
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<T, i8> || std::is_same_v<T, i16> || std::is_same_v<T, i32>)
|
||||||
|
{
|
||||||
|
return static_cast<T>(std::stoi(temp));
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, i64>)
|
||||||
|
{
|
||||||
|
return static_cast<i64>(std::stoll(temp));
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, u8> || std::is_same_v<T, u16> || std::is_same_v<T, u32>)
|
||||||
|
{
|
||||||
|
return static_cast<T>(std::stoul(temp));
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, u64>)
|
||||||
|
{
|
||||||
|
return static_cast<u64>(std::stoull(temp));
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, float>)
|
||||||
|
{
|
||||||
|
return std::stof(temp);
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, double>)
|
||||||
|
{
|
||||||
|
return std::stod(temp);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
static_assert(std::is_arithmetic_v<T>, "Unsupported type for this specialization");
|
||||||
|
}
|
||||||
|
BLT_UNREACHABLE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void test();
|
void test();
|
||||||
}
|
}
|
||||||
|
@ -115,7 +155,7 @@ namespace blt::argparse
|
||||||
size_t start = m_argument.size();
|
size_t start = m_argument.size();
|
||||||
for (auto [i, c] : enumerate(m_argument))
|
for (auto [i, c] : enumerate(m_argument))
|
||||||
{
|
{
|
||||||
if (std::isalnum(c))
|
if (!detail::prefix_characters_set.contains(c))
|
||||||
{
|
{
|
||||||
start = i;
|
start = i;
|
||||||
break;
|
break;
|
||||||
|
@ -140,38 +180,37 @@ namespace blt::argparse
|
||||||
class argument_consumer_t
|
class argument_consumer_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
argument_consumer_t(const i32 argc, const char** argv): argv(argv), argc(argc)
|
explicit argument_consumer_t(const span<argument_string_t>& args): args(args)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::string_view peek(const i32 offset = 0) const
|
[[nodiscard]] argument_string_t peek(const i32 offset = 0) const
|
||||||
{
|
{
|
||||||
return argv[forward_index + offset];
|
return args[forward_index + offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view consume()
|
argument_string_t consume()
|
||||||
{
|
{
|
||||||
return argv[forward_index++];
|
return args[forward_index++];
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] i32 position() const
|
[[nodiscard]] i32 position() const
|
||||||
{
|
{
|
||||||
return argc;
|
return forward_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] i32 remaining() const
|
[[nodiscard]] i32 remaining() const
|
||||||
{
|
{
|
||||||
return argc - forward_index;
|
return static_cast<i32>(args.size()) - forward_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool has_next(const i32 offset = 0) const
|
[[nodiscard]] bool has_next(const i32 offset = 0) const
|
||||||
{
|
{
|
||||||
return (offset + forward_index) < argc;
|
return (offset + forward_index) < args.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char** argv;
|
span<argument_string_t> args;
|
||||||
i32 argc;
|
|
||||||
i32 forward_index = 0;
|
i32 forward_index = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,15 @@ namespace blt::argparse
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hashset_t<char> prefix_characters()
|
||||||
|
{
|
||||||
|
hashset_t<char> result;
|
||||||
|
for (auto [i, v] : enumerate(allowed_flag_prefixes))
|
||||||
|
for (auto c : v)
|
||||||
|
result.insert(c);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,16 +109,9 @@ namespace blt::argparse
|
||||||
// Test Case 9: Validate edge case of an argument with spaces
|
// Test Case 9: Validate edge case of an argument with spaces
|
||||||
void test_argument_string_t_with_spaces()
|
void test_argument_string_t_with_spaces()
|
||||||
{
|
{
|
||||||
try
|
const argument_string_t arg(" ");
|
||||||
{
|
BLT_ASSERT(!arg.is_flag() && "Arguments with spaces should not be treated as flags.");
|
||||||
const argument_string_t arg(" ");
|
BLT_ASSERT(arg.value() == " " && "Arguments with spaces should match the input string.");
|
||||||
BLT_ASSERT(!arg.is_flag() && "Arguments with spaces should not be treated as flags.");
|
|
||||||
BLT_ASSERT(arg.value() == " " && "Arguments with spaces should match the input string.");
|
|
||||||
} catch (bad_flag&)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BLT_ASSERT(false && "Expected an exception to be thrown for arguments with spaces.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test Case 10: Validate arguments with numeric characters
|
// Test Case 10: Validate arguments with numeric characters
|
||||||
|
@ -120,6 +122,33 @@ namespace blt::argparse
|
||||||
BLT_ASSERT(arg.value() == "123" && "Numeric flag value should match the input string.");
|
BLT_ASSERT(arg.value() == "123" && "Numeric flag value should match the input string.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Test Case 11: Ensure the constructor handles '+' flag correctly
|
||||||
|
void test_argument_string_t_plus_flag_basic()
|
||||||
|
{
|
||||||
|
const argument_string_t arg("+f");
|
||||||
|
BLT_ASSERT(arg.is_flag() && "Expected argument to be identified as a flag.");
|
||||||
|
BLT_ASSERT(arg.value() == "f" && "Plus flag value should match the input string.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Case 13: Handle edge case of a single plus (`+`) which might be ambiguous
|
||||||
|
void test_argument_string_t_single_plus()
|
||||||
|
{
|
||||||
|
const argument_string_t arg("+");
|
||||||
|
BLT_ASSERT(arg.is_flag() && "Expected single plus (`+`) to be treated as a flag.");
|
||||||
|
BLT_ASSERT(arg.value().empty() && "Single plus flag should have empty value.");
|
||||||
|
BLT_ASSERT(arg.get_flag() == "+" && "Single plus flag should match the input string.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Case 14: Handle arguments with prefix only (like '++')
|
||||||
|
void test_argument_string_t_double_plus()
|
||||||
|
{
|
||||||
|
const argument_string_t arg("++");
|
||||||
|
BLT_ASSERT(arg.is_flag() && "Double plus ('++') should be treated as a flag.");
|
||||||
|
BLT_ASSERT(arg.value().empty() && "Double plus flag should have empty value.");
|
||||||
|
BLT_ASSERT(arg.get_flag() == "++" && "Double plus value should match the input string.");
|
||||||
|
}
|
||||||
|
|
||||||
void run_all_tests_argument_string_t()
|
void run_all_tests_argument_string_t()
|
||||||
{
|
{
|
||||||
test_argument_string_t_flag_basic();
|
test_argument_string_t_flag_basic();
|
||||||
|
@ -130,7 +159,11 @@ namespace blt::argparse
|
||||||
test_argument_string_t_double_hyphen();
|
test_argument_string_t_double_hyphen();
|
||||||
test_argument_string_t_with_spaces();
|
test_argument_string_t_with_spaces();
|
||||||
test_argument_string_t_numeric_flag();
|
test_argument_string_t_numeric_flag();
|
||||||
|
test_argument_string_t_plus_flag_basic();
|
||||||
|
test_argument_string_t_single_plus();
|
||||||
|
test_argument_string_t_double_plus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void test()
|
void test()
|
||||||
{
|
{
|
||||||
run_all_tests_argument_string_t();
|
run_all_tests_argument_string_t();
|
||||||
|
|
Loading…
Reference in New Issue