poaflocParser 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 |
option.cpp (3129B)
0 #include <algorithm>
2 #include <based/char/character.hpp>
3 #include <based/char/is/alpha.hpp>
4 #include <based/char/is/alpha_lower.hpp>
5 #include <based/char/is/digit.hpp>
6 #include <based/char/mapper.hpp>
7 #include <based/functional/predicate/not_null.hpp>
8 #include <based/trait/iterator.hpp>
10 #include "poafloc/error.hpp"
11 #include "poafloc/poafloc.hpp"
13 namespace
14 {
16 struct short_map
17 {
18 constexpr bool operator()(based::character chr) const
19 {
20 return based::is_alpha(chr) || chr == '?';
21 }
22 };
24 struct long_map
25 {
26 constexpr bool operator()(based::character chr) const
27 {
28 return based::is_alpha_lower(chr) || based::is_digit(chr);
29 }
30 };
32 using short_mapper = based::mapper<short_map>;
33 using long_mapper = based::mapper<long_map>;
35 } // namespace
37 // option_short
38 namespace poafloc::detail
39 {
41 constexpr bool option_short::is_valid(based::character chr)
42 {
43 return short_mapper::predicate(chr);
44 }
46 bool option_short::has(based::character chr) const
47 {
48 return m_opts[short_mapper::map(chr)] != sentinel;
49 }
51 bool option_short::set(based::character chr, value_type value)
52 {
53 if (!is_valid(chr)) {
54 throw error<error_code::invalid_option>(chr);
55 }
57 if (has(chr)) {
58 return false;
59 }
61 m_opts[short_mapper::map(chr)] = value;
62 return true;
63 }
65 option_short::opt_type option_short::get(based::character chr) const
66 {
67 if (!is_valid(chr)) {
68 throw error<error_code::invalid_option>(chr);
69 }
71 if (!has(chr)) {
72 return {};
73 }
75 return m_opts[short_mapper::map(chr)];
76 }
78 } // namespace poafloc::detail
80 // trie_t
81 namespace poafloc::detail
82 {
84 bool trie_t::set(trie_t& trie, std::string_view key, value_type value)
85 {
86 trie_t* crnt = ≜
87 for (const auto c : key) {
88 crnt->m_count++;
89 if (!crnt->m_terminal) {
90 crnt->m_value = value;
91 }
93 const auto idx = long_mapper::map(c);
94 if (crnt->m_children[idx] == nullptr) {
95 crnt->m_children[idx] = std::make_unique<trie_t>(nullptr);
96 }
97 crnt = crnt->m_children[idx].get();
98 }
100 if (crnt->m_terminal) {
101 return false;
102 }
104 crnt->m_value = value;
105 crnt->m_terminal = true;
106 return true;
107 }
109 trie_t::opt_type trie_t::get(const trie_t& trie, std::string_view key)
110 {
111 const trie_t* crnt = ≜
113 for (const auto c : key) {
114 const auto idx = long_mapper::map(c);
115 if (crnt->m_children[idx] == nullptr) {
116 return {};
117 }
118 crnt = crnt->m_children[idx].get();
119 }
121 if (crnt->m_terminal || crnt->m_count == 1_u8) {
122 return crnt->m_value;
123 }
125 return {};
126 }
128 } // namespace poafloc::detail
130 // option_long
131 namespace poafloc::detail
132 {
134 constexpr bool option_long::is_valid(std::string_view opt)
135 {
136 return based::is_alpha_lower(opt.front())
137 && std::ranges::all_of(opt, long_mapper::predicate);
138 }
140 bool option_long::set(std::string_view opt, value_type idx)
141 {
142 if (!is_valid(opt)) {
143 throw error<error_code::invalid_option>(opt);
144 }
146 return trie_t::set(m_trie, opt, idx);
147 }
149 option_long::opt_type option_long::get(std::string_view opt) const
150 {
151 if (!is_valid(opt)) {
152 throw error<error_code::invalid_option>(opt);
153 }
155 return trie_t::get(m_trie, opt);
156 }
158 } // namespace poafloc::detail