commit 6fb3d52a73320c8c3149e3b316d7c17f9294e0e8
parent 3316f7b8c285980ab7a83d398bba7caf0664f632
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Tue, 11 Jun 2024 12:12:38 +0200
Improve trie_t
* Rule of 5
* Check option validity
* All long options must be lowercase
Diffstat:
3 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/include/args.hpp b/include/args.hpp
@@ -50,12 +50,19 @@ class Parser {
class trie_t {
public:
+ trie_t() = default;
+ trie_t(const trie_t &) = delete;
+ trie_t(trie_t &&) = delete;
+ trie_t &operator=(const trie_t &) = delete;
+ trie_t &operator=(trie_t &&) = delete;
~trie_t() noexcept;
- void insert(const std::string &option, int key);
- int get(const std::string &option) const;
+ bool insert(const char *option, int key);
+ int get(const char *option) const;
private:
+ static bool is_valid(const char *option);
+
trie_t *children[26] = {0};
int count = 0;
int key = 0;
diff --git a/src/args.cpp b/src/args.cpp
@@ -38,7 +38,10 @@ Parser::Parser(const argp_t *argp, void *input) : argp(argp), m_input(input) {
continue;
}
- trie.insert(opt.name, key_last);
+ if (!trie.insert(opt.name, key_last)) {
+ // option not valid, silently ignoring
+ continue;
+ }
if (hidden) continue;
if (opt.flags & Option::HIDDEN) continue;
@@ -152,7 +155,7 @@ int Parser::parse(int argc, char *argv[], void *input) {
usage(argv[0]);
}
- const int key = trie.get(opt_s);
+ const int key = trie.get(opt_s.data());
if (!key) goto unknown;
diff --git a/src/trie.cpp b/src/trie.cpp
@@ -10,27 +10,31 @@ Parser::trie_t::~trie_t() noexcept {
}
}
-void Parser::trie_t::insert(const std::string &option, int key) {
+bool Parser::trie_t::insert(const char *option, int key) {
trie_t *crnt = this;
- for (const char c : option) {
+ if (!is_valid(option)) return false;
+ for (; *option; option++) {
if (!crnt->terminal) crnt->key = key;
crnt->count++;
- const uint8_t idx = c - 'a';
+ const uint8_t idx = *option - 'a';
if (!crnt->children[idx]) crnt->children[idx] = new trie_t();
crnt = crnt->children[idx];
}
crnt->terminal = true;
crnt->key = key;
+
+ return true;
}
-int Parser::trie_t::get(const std::string &option) const {
+int Parser::trie_t::get(const char *option) const {
const trie_t *crnt = this;
- for (const char c : option) {
- const uint8_t idx = c - 'a';
+ if (!is_valid(option)) return 0;
+ for (; *option; option++) {
+ const uint8_t idx = *option - 'a';
if (!crnt->children[idx]) return 0;
crnt = crnt->children[idx];
}
@@ -39,4 +43,11 @@ int Parser::trie_t::get(const std::string &option) const {
return crnt->key;
}
+bool Parser::trie_t::is_valid(const char *option) {
+ for (; *option; option++) {
+ if (!std::islower(*option)) return false;
+ }
+ return true;
+}
+
} // namespace args