poafloc

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

commit 6fb3d52a73320c8c3149e3b316d7c17f9294e0e8
parent 3316f7b8c285980ab7a83d398bba7caf0664f632
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Tue, 11 Jun 2024 10:12:38 +0200

Improve trie_t

* Rule of 5
* Check option validity
* All long options must be lowercase

Diffstat:
M include/args.hpp | +++++++++ --
M src/args.cpp | +++++ --
M src/trie.cpp | +++++++++++++++++ ------

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