diff --git a/arg_parse_variant_map.drawio b/arg_parse_variant_map.drawio new file mode 100644 index 0000000..ac232d8 --- /dev/null +++ b/arg_parse_variant_map.drawio @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/blt_argparse_variant_map.png b/blt_argparse_variant_map.png new file mode 100644 index 0000000..adaf7f0 Binary files /dev/null and b/blt_argparse_variant_map.png differ diff --git a/include/blt/parse/argparse.h b/include/blt/parse/argparse.h index 54d67bc..476dacf 100755 --- a/include/blt/parse/argparse.h +++ b/include/blt/parse/argparse.h @@ -57,7 +57,8 @@ namespace blt arg_vector_t(std::initializer_list f): flags(f) { - if (flags.size() == 1) { + if (flags.size() == 1) + { if (!blt::string::starts_with(flags[0], '-')) { name = flags[0]; @@ -325,22 +326,6 @@ namespace blt return static_cast(std::stoll(s)); return static_cast(std::stoull(s)); } - - private: - struct - { - friend arg_parse; - private: - std::vector arg_properties_storage; - size_t max_line_length = 80; - // TODO: grouping like git's help - // pre/postfix applied to the help message - std::string prefix; - std::string postfix; - public: - std::vector name_associations; - HASHMAP flag_associations; - } user_args; struct arg_results { @@ -385,7 +370,24 @@ namespace blt return data.find(key.substr(1)) != data.end(); return data.find(key) != data.end(); } - } loaded_args; + }; + private: + struct + { + friend arg_parse; + private: + std::vector arg_properties_storage; + size_t max_line_length = 80; + // TODO: grouping like git's help + // pre/postfix applied to the help message + std::string prefix; + std::string postfix; + public: + std::vector name_associations; + HASHMAP flag_associations; + } user_args; + + arg_results loaded_args; bool subcommand_found = false; bool use_full_name = false; @@ -478,6 +480,8 @@ namespace blt std::string to_string(const blt::arg_data_internal_t& v); + std::string to_string(const blt::arg_data_vec_t& v); + } #endif //BLT_TESTS_ARGPARSE_H diff --git a/include/blt/std/ranges.h b/include/blt/std/ranges.h index 9f9ba7e..80c87c2 100644 --- a/include/blt/std/ranges.h +++ b/include/blt/std/ranges.h @@ -93,6 +93,12 @@ namespace blt return enumerator{container.begin(), container.end()}; } + template + static inline auto enumerate(T&& container) + { + return enumerator{container.begin(), container.end()}; + } + template struct range { @@ -168,6 +174,42 @@ namespace blt } }; + template + class itr_offset + { + private: + I begin_; + I end_; + public: + template + itr_offset(I begin, I end, T offset): begin_(begin), end_(end) + { + for (T t = 0; t < offset; t++) + ++begin_; + } + + template + itr_offset(C& container, T offset): begin_(container.begin()), end_(container.end()) + { + for (T t = 0; t < offset; t++) + ++begin_; + } + + auto begin() + { + return begin_; + } + + auto end() + { + return end_; + } + }; + + template + itr_offset(C, T) -> itr_offset; + + inline constexpr std::size_t dynamic_extent = std::numeric_limits::max(); template @@ -182,7 +224,7 @@ namespace blt using const_pointer = const T*; using reference = T&; using const_reference = const T&; - + private: public: diff --git a/include/blt/std/string.h b/include/blt/std/string.h index d4b82b2..43ea9c9 100755 --- a/include/blt/std/string.h +++ b/include/blt/std/string.h @@ -216,31 +216,67 @@ namespace blt::string // taken from https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c // extended to return a vector - static inline BLT_CPP20_CONSTEXPR std::vector split(std::string s, std::string_view delim) + static inline BLT_CPP20_CONSTEXPR std::vector split(std::string_view s, std::string_view delim) { size_t pos = 0; + size_t from = 0; std::vector tokens; - while ((pos = s.find(delim)) != std::string::npos) + while ((pos = s.find(delim, from)) != std::string::npos) { - auto token = s.substr(0, pos); - tokens.push_back(token); - s.erase(0, pos + delim.length()); + auto size = pos - from; + auto token = s.substr(from, size); + tokens.emplace_back(token); + from += size + delim.length(); } - tokens.push_back(std::move(s)); + tokens.emplace_back(s.substr(from)); + return tokens; + } + + static inline BLT_CPP20_CONSTEXPR std::vector split(std::string_view s, char delim) + { + size_t pos = 0; + size_t from = 0; + std::vector tokens; + while ((pos = s.find(delim, from)) != std::string::npos) + { + auto size = pos - from; + auto token = s.substr(from, size); + tokens.emplace_back(token); + from += size + 1; + } + tokens.emplace_back(s.substr(from)); return tokens; } - static inline BLT_CPP20_CONSTEXPR std::vector split(std::string s, char delim) + static inline BLT_CPP20_CONSTEXPR std::vector split_sv(std::string_view s, std::string_view delim) { size_t pos = 0; - std::vector tokens; - while ((pos = s.find(delim)) != std::string::npos) + size_t from = 0; + std::vector tokens; + while ((pos = s.find(delim, from)) != std::string::npos) { - auto token = s.substr(0, pos); + auto size = pos - from; + auto token = s.substr(from, size); tokens.push_back(token); - s.erase(0, pos + 1); + from += size + delim.length(); } - tokens.push_back(s); + tokens.push_back(s.substr(from)); + return tokens; + } + + static inline BLT_CPP20_CONSTEXPR std::vector split_sv(std::string_view s, char delim) + { + size_t pos = 0; + size_t from = 0; + std::vector tokens; + while ((pos = s.find(delim, from)) != std::string::npos) + { + auto size = pos - from; + auto token = s.substr(from, size); + tokens.push_back(token); + from += size + 1; + } + tokens.push_back(s.substr(from)); return tokens; } diff --git a/src/blt/parse/argparse.cpp b/src/blt/parse/argparse.cpp index 247468d..92daea9 100755 --- a/src/blt/parse/argparse.cpp +++ b/src/blt/parse/argparse.cpp @@ -7,6 +7,7 @@ #include #include #include +#include "blt/std/utility.h" namespace blt { @@ -92,36 +93,44 @@ namespace blt std::string to_string(const arg_data_t& v) { - if (std::holds_alternative(v)) - return to_string(std::get(v)); - else if (std::holds_alternative(v)) - { - const auto& vec = std::get(v); - if (vec.size() == 1) - return to_string(vec[0]); - if (vec.empty()) - return "Empty Vector"; - std::string str; - for (const auto& r : vec) - { - str += to_string(r); - str += ' '; - } - return "Vector of contents: " + str; - } - return "Empty"; + return std::visit(blt::lambda_visitor{ + [](const arg_data_internal_t& v) { + return to_string(v); + }, + [](const arg_data_vec_t& v) { + return to_string(v); + } + }, v); } std::string to_string(const arg_data_internal_t& v) { - if (std::holds_alternative(v)) + return std::visit(blt::lambda_visitor{ + [&](const std::string& str) { + return str; + }, + [&](bool b) { + return std::string(b ? "True" : "False"); + }, + [&](int32_t i) { + return std::to_string(i); + } + }, v); + } + + std::string to_string(const blt::arg_data_vec_t& vec) + { + std::string result = "["; + + for (const auto& value : blt::enumerate(vec)) { - return std::get(v); - } else if (std::holds_alternative(v)) - { - return std::get(v) ? "True" : "False"; + result += to_string(value.second); + if (value.first != vec.size() - 1) + result += ", "; } - return std::to_string(std::get(v)); + result += "]"; + + return result; } std::string arg_parse::filename(const std::string& path) diff --git a/tests/include/string_tests.h b/tests/include/string_tests.h new file mode 100644 index 0000000..d44fdc4 --- /dev/null +++ b/tests/include/string_tests.h @@ -0,0 +1,27 @@ +/* + * + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef BLT_TESTS_STRING_H +#define BLT_TESTS_STRING_H + +namespace blt::test +{ + void run_string_test(); +} + +#endif diff --git a/tests/src/string_tests.cpp b/tests/src/string_tests.cpp new file mode 100644 index 0000000..4f3216e --- /dev/null +++ b/tests/src/string_tests.cpp @@ -0,0 +1,59 @@ +/* + * + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include +#include + +namespace blt::test +{ + void run_string_test() + { + std::string str = "I HAVE A LOT OF\tTABULAR\tFORMED MEMORIES"; + + auto s_splits_c = blt::string::split(str, ' '); + auto s_splits_s = blt::string::split(str, "LOT"); + + auto sv_splits_c = blt::string::split_sv(str, ' '); + auto sv_splits_s = blt::string::split_sv(str, "LOT"); + + for (auto v : blt::enumerate(s_splits_c)) + { + if (v.second != sv_splits_c[v.first]) + { + BLT_WARN("THEY DO NOT MATCH!!! '%s' vs '%s'", v.second.c_str(), std::string(sv_splits_c[v.first]).c_str()); + } else + { + BLT_DEBUG(v.second); + } + } + + BLT_INFO(""); + + for (auto v : blt::enumerate(s_splits_s)) + { + if (v.second != sv_splits_s[v.first]) + { + BLT_WARN("THEY DO NOT MATCH!!! '%s' vs '%s'", v.second.c_str(), std::string(sv_splits_s[v.first]).c_str()); + } else + { + BLT_DEBUG(v.second); + } + } + } +} \ No newline at end of file