poafloc

poafloc - Parser Of Arguments For Lines Of Commands
git clone git://git.dimitrijedobrota.com/poafloc.git
Log | Files | Refs | README | LICENSE

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:
Minclude/args.hpp | 11+++++++++--
Msrc/args.cpp | 7+++++--
Msrc/trie.cpp | 23+++++++++++++++++------
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