From 44a57e5ec2708d6c0a509a24c641d7ade78273d4 Mon Sep 17 00:00:00 2001 From: Brett Date: Thu, 13 Feb 2025 01:53:21 -0500 Subject: [PATCH] i am tired --- CMakeLists.txt | 2 +- include/blt/parse/argparse_v2.h | 62 +++++++++------------ src/blt/parse/argparse_v2.cpp | 95 ++++++++++++--------------------- 3 files changed, 59 insertions(+), 100 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c7db4fe..26d0783 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 4.0.3) +set(BLT_VERSION 4.0.4) set(BLT_TARGET BLT) diff --git a/include/blt/parse/argparse_v2.h b/include/blt/parse/argparse_v2.h index d047e69..3ef50d8 100644 --- a/include/blt/parse/argparse_v2.h +++ b/include/blt/parse/argparse_v2.h @@ -44,14 +44,6 @@ namespace blt::argparse namespace detail { - inline hashset_t allowed_flag_prefixes = {"-", "--", "+"}; - - std::string flag_prefixes_as_string(); - hashset_t prefix_characters(); - - 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 { public: @@ -111,24 +103,22 @@ namespace blt::argparse class argument_string_t { public: - explicit argument_string_t(const char* input): m_argument(input) + explicit argument_string_t(const char* input, const hashset_t& allowed_flag_prefix): m_argument(input), + allowed_flag_prefix(&allowed_flag_prefix) { if (input == nullptr) throw detail::bad_flag("Argument cannot be null!"); + process_argument(); } [[nodiscard]] std::string_view get_flag() const { - if (!m_flag_section) - process_argument(); - return *m_flag_section; + return m_flag_section; } [[nodiscard]] std::string_view get_name() const { - if (!m_name_section) - process_argument(); - return *m_name_section; + return m_name_section; } [[nodiscard]] std::string_view value() const @@ -138,9 +128,7 @@ namespace blt::argparse [[nodiscard]] bool is_flag() const { - if (!m_is_flag) - process_argument(); - return *m_is_flag; + return !m_flag_section.empty(); } [[nodiscard]] std::string_view get_argument() const @@ -149,31 +137,21 @@ namespace blt::argparse } private: - void process_argument() const + void process_argument() { - size_t start = m_argument.size(); - for (auto [i, c] : enumerate(m_argument)) + size_t start = 0; + for (; start < m_argument.size() && allowed_flag_prefix->contains(m_argument[start]); start++) { - if (!detail::prefix_characters_set.contains(c)) - { - start = i; - break; - } } - m_is_flag = (start != 0); + m_flag_section = {m_argument.data(), start}; m_name_section = {m_argument.data() + start, m_argument.size() - start}; - - if (!m_flag_section->empty() && !detail::allowed_flag_prefixes.contains(*m_flag_section)) - throw detail::bad_flag( - "Invalid flag " + std::string(*m_flag_section) + " detected, flag is not in allowed list of flags! Must be one of " + - detail::flag_prefix_list_string); } std::string_view m_argument; - mutable std::optional m_is_flag; - mutable std::optional m_flag_section; - mutable std::optional m_name_section; + std::string_view m_flag_section; + std::string_view m_name_section; + const hashset_t* allowed_flag_prefix; }; class argument_consumer_t @@ -230,8 +208,8 @@ namespace blt::argparse class argument_parser_t { public: - argument_parser_t(const std::optional name = {}, const std::optional usage = {}): - m_name(name.value_or(std::optional{})), m_usage(usage.value_or(std::optional{})) + explicit argument_parser_t(const std::optional name = {}, const std::optional usage = {}): + m_name(name), m_usage(usage) { } @@ -252,8 +230,16 @@ namespace blt::argparse { public: - private: + argument_parser_t add_subparser(const std::string_view dest) + { + } + + argument_parser_t add_subparser(std::string& dest) + { + + } + private: }; } diff --git a/src/blt/parse/argparse_v2.cpp b/src/blt/parse/argparse_v2.cpp index 09fcee3..02cb76b 100644 --- a/src/blt/parse/argparse_v2.cpp +++ b/src/blt/parse/argparse_v2.cpp @@ -22,34 +22,7 @@ namespace blt::argparse { namespace detail { - std::string flag_prefixes_as_string() - { - std::string result; - for (auto [i, v] : enumerate(allowed_flag_prefixes)) - { - result += '\''; - result += v; - result += '\''; - if (i != allowed_flag_prefixes.size() - 2) - result += ", "; - else if (i != allowed_flag_prefixes.size() - 1) - { - if (allowed_flag_prefixes.size() > 2) - result += ','; - result += " or "; - } - } - return result; - } - hashset_t prefix_characters() - { - hashset_t result; - for (auto [i, v] : enumerate(allowed_flag_prefixes)) - for (auto c : v) - result.insert(c); - return result; - } } @@ -57,93 +30,92 @@ namespace blt::argparse { // Unit Tests for class argument_string_t // Test Case 1: Ensure the constructor handles flags correctly - void test_argument_string_t_flag_basic() + void test_argument_string_t_flag_basic(const hashset_t& prefixes) { - const argument_string_t arg("-f"); + const argument_string_t arg("-f", prefixes); BLT_ASSERT(arg.is_flag() && "Expected argument to be identified as a flag."); BLT_ASSERT(arg.value() == "f" && "Flag value should match the input string."); } // Test Case 2: Ensure the constructor handles long flags correctly - void test_argument_string_t_long_flag() + void test_argument_string_t_long_flag(const hashset_t& prefixes) { - const argument_string_t arg("--file"); + const argument_string_t arg("--file", prefixes); BLT_ASSERT(arg.is_flag() && "Expected argument to be identified as a flag."); BLT_ASSERT(arg.value() == "file" && "Long flag value should match the input string."); } // Test Case 3: Ensure positional arguments are correctly identified - void test_argument_string_t_positional_argument() + void test_argument_string_t_positional_argument(const hashset_t& prefixes) { - const argument_string_t arg("filename.txt"); + const argument_string_t arg("filename.txt", prefixes); BLT_ASSERT(!arg.is_flag() && "Expected argument to be identified as positional."); BLT_ASSERT(arg.value() == "filename.txt" && "Positional argument value should match the input string."); } // Test Case 5: Handle an empty string - void test_argument_string_t_empty_input() + void test_argument_string_t_empty_input(const hashset_t& prefixes) { - const argument_string_t arg(""); + const argument_string_t arg("", prefixes); BLT_ASSERT(!arg.is_flag() && "Expected an empty input to be treated as positional, not a flag."); BLT_ASSERT(arg.value().empty() && "Empty input should have an empty value."); } // Test Case 6: Handle edge case of a single hyphen (`-`) which might be ambiguous - void test_argument_string_t_single_hyphen() + void test_argument_string_t_single_hyphen(const hashset_t& prefixes) { - const argument_string_t arg("-"); + const argument_string_t arg("-", prefixes); BLT_ASSERT(arg.is_flag() && "Expected single hyphen (`-`) to be treated as a flag."); BLT_ASSERT(arg.value().empty() && "Single hyphen flag should have empty value."); BLT_ASSERT(arg.get_flag() == "-" && "Single hyphen flag should match the input string."); } // Test Case 8: Handle arguments with prefix only (like "--") - void test_argument_string_t_double_hyphen() + void test_argument_string_t_double_hyphen(const hashset_t& prefixes) { - const argument_string_t arg("--"); + const argument_string_t arg("--", prefixes); BLT_ASSERT(arg.is_flag() && "Double hyphen ('--') should be treated as a flag."); BLT_ASSERT(arg.value().empty() && "Double hyphen flag should have empty value."); BLT_ASSERT(arg.get_flag() == "--" && "Double hyphen value should match the input string."); } // 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(const hashset_t& prefixes) { - const argument_string_t arg(" "); + const argument_string_t arg(" ", prefixes); 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."); } // Test Case 10: Validate arguments with numeric characters - void test_argument_string_t_numeric_flag() + void test_argument_string_t_numeric_flag(const hashset_t& prefixes) { - const argument_string_t arg("-123"); + const argument_string_t arg("-123", prefixes); BLT_ASSERT(arg.is_flag() && "Numeric flags should still be treated as flags."); 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() + void test_argument_string_t_plus_flag_basic(const hashset_t& prefixes) { - const argument_string_t arg("+f"); + const argument_string_t arg("+f", prefixes); 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() + void test_argument_string_t_single_plus(const hashset_t& prefixes) { - const argument_string_t arg("+"); + const argument_string_t arg("+", prefixes); 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() + void test_argument_string_t_double_plus(const hashset_t& prefixes) { - const argument_string_t arg("++"); + const argument_string_t arg("++", prefixes); 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."); @@ -151,17 +123,18 @@ namespace blt::argparse void run_all_tests_argument_string_t() { - test_argument_string_t_flag_basic(); - test_argument_string_t_long_flag(); - test_argument_string_t_positional_argument(); - test_argument_string_t_empty_input(); - test_argument_string_t_single_hyphen(); - test_argument_string_t_double_hyphen(); - test_argument_string_t_with_spaces(); - 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(); + const hashset_t prefixes = {'-', '+'}; + test_argument_string_t_flag_basic(prefixes); + test_argument_string_t_long_flag(prefixes); + test_argument_string_t_positional_argument(prefixes); + test_argument_string_t_empty_input(prefixes); + test_argument_string_t_single_hyphen(prefixes); + test_argument_string_t_double_hyphen(prefixes); + test_argument_string_t_with_spaces(prefixes); + test_argument_string_t_numeric_flag(prefixes); + test_argument_string_t_plus_flag_basic(prefixes); + test_argument_string_t_single_plus(prefixes); + test_argument_string_t_double_plus(prefixes); } void test()