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 |

commit6fb3d52a73320c8c3149e3b316d7c17f9294e0e8
parent3316f7b8c285980ab7a83d398bba7caf0664f632
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateTue, 11 Jun 2024 10:12:38 +0200

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

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