Argx 1.0.0-build
Simple argument parser made in C++
 
Loading...
Searching...
No Matches
Argx.cpp
Go to the documentation of this file.
1/* src/argx.cpp
2 * Owned and created by: pcannon09
3 */
4
5#include <string>
6#include <iostream>
7#include <codecvt>
8#include <locale>
9
10#include "../inc/Argx.hpp"
12#include "../inc/types.hpp"
13
14namespace argx
15{
16 // PRIVATE
17 std::vector<ARGXOptions> Argx::options;
18 std::vector<std::string> *Argx::mainArgs = nullptr;
19
20 unsigned int Argx::mainArgc;
21
22 // PUBLIC:
23 Argx::Argx(const std::string &id, int argc, char *argv[])
24 : id(id)
25 {
26 this->mainArgs = new std::vector<std::string>(argv, argv + argc);
27 this->mainArgc = argc;
28 }
29
31 { }
32
34 {
35 delete this->mainArgs; this->mainArgs = nullptr;
36 }
37
38 void Argx::add(ARGXOptions option) const
39 {
40 ARGXError error = {
41 .type = "success",
42 .code = 0
43 };
44
45 this->options.emplace_back(option);
46 }
47
48 int Argx::findParam(const std::string &id)
49 {
50 // First check if it's a main parameter
51 for (size_t i = 0; i < this->options.size(); i++)
52 {
53 if (this->options[i].id == id)
54 {
55 // Check if this main parameter exists in arguments
56 for (const std::string &arg : *this->mainArgs)
57 {
58 if (arg == this->options[i].param || arg == this->options[i].sparam)
59 {
60 return static_cast<int>(i);
61 }
62 }
63 }
64 }
65
66 // Then look for sub-parameters
67 for (const auto &opt : this->options)
68 {
69 // Check if the parent option exists in the arguments
70 bool parentExists = false;
71
72 for (const std::string &arg : *this->mainArgs)
73 {
74 if (arg == opt.param || arg == opt.sparam)
75 {
76 parentExists = true;
77 break;
78 }
79 }
80
81 if (parentExists)
82 {
83 // Find the index of the requested sub-parameter
84 for (size_t i = 0; i < opt.subParams.size(); i++)
85 {
86 if (opt.subParams[i].id == id) return static_cast<int>(i);
87 }
88 }
89 }
90
91 return -1; // Not found
92 }
93
94 bool Argx::paramExists(const std::string &id)
95 {
96 if (this->findParam(id) >= 0) return true;;
97
98 return false;
99 }
100
101
102
103 ARGXParam Argx::getParam(const std::string &id)
104 {
105 if (this->mainArgc <= 1) return {};
106
107 ARGXParam result;
108
109 // First, check if this is a top-level option
110 for (const auto &opt : this->options)
111 {
112 if (opt.id == id)
113 {
114 // Find the position of the main option in arguments
115 int mainOptionPos = -1;
116
117 for (size_t i = 0; i < this->mainArgs->size(); ++i)
118 {
119 if ((*this->mainArgs)[i] == opt.param || (*this->mainArgs)[i] == opt.sparam)
120 {
121 result.exists = true;
122 mainOptionPos = i;
123 break;
124 }
125 }
126
127 if (result.exists)
128 {
129 if (opt.hasSubParams)
130 {
131 // Check each sub-parameter
132 for (const auto &sub : opt.subParams)
133 {
134 bool subMatched = false;
135
136 // Look for sub-parameters after the main option
137 for (size_t i = mainOptionPos + 1; i < this->mainArgs->size(); ++i)
138 {
139 if ((*this->mainArgs)[i] == sub.param || (*this->mainArgs)[i] == sub.sparam)
140 {
141 subMatched = true;
142 break;
143 }
144 }
145
146 result.subExists.push_back(subMatched);
147 }
148 }
149
150 return result;
151 }
152 }
153 }
154
155 // If not found as top-level, check if it's a sub-parameter
156 for (const auto &opt : this->options)
157 {
158 // Find if the parent option exists and get its position
159 size_t parentPos = -1;
160
161 for (size_t i = 0; i < this->mainArgs->size(); ++i)
162 {
163 if ((*this->mainArgs)[i] == opt.param || (*this->mainArgs)[i] == opt.sparam)
164 {
165 parentPos = i;
166 break;
167 }
168 }
169
170 if (parentPos > -1 && opt.hasSubParams)
171 {
172 // Check if the requested sub-parameter exists after the parent
173 for (const auto &sub : opt.subParams)
174 {
175 if (sub.id == id)
176 {
177 for (size_t i = parentPos + 1; i < this->mainArgs->size(); ++i)
178 {
179 if ((*this->mainArgs)[i] == sub.param || (*this->mainArgs)[i] == sub.sparam)
180 {
181 result.exists = true;
182 break;
183 }
184 }
185
186 if (!result.exists && parentPos + 1 < this->mainArgs->size())
187 {
188 std::string nextArg = (*this->mainArgs)[parentPos + 1];
189
190 if (nextArg == sub.param || nextArg == sub.sparam) result.exists = true;
191 }
192
193 // Handle any sub-sub-parameters if they exist
194 if (result.exists && sub.hasSubParams)
195 {
196 for (const auto &subsub : sub.subParams)
197 {
198 bool subsubMatched = false;
199
200 for (size_t i = 0; i < this->mainArgs->size(); ++i)
201 {
202 if ((*this->mainArgs)[i] == subsub.param || (*this->mainArgs)[i] == subsub.sparam)
203 {
204 subsubMatched = true;
205 break;
206 }
207 }
208
209 result.subExists.push_back(subsubMatched);
210 }
211 }
212
213 return result;
214 }
215 }
216 }
217 }
218
219 return result;
220 }
221
222 bool Argx::getSubParam(const argx::ARGXParam &param, const std::string &id)
223 { return this->paramExists(id) && param.subExists[this->findParam(id)]; }
224
225 std::string Argx::createDocs(ARGXStyle style, const std::string &title, const std::string &mainInfo)
226 {
227 std::string contentStr;
228
229 if (style == ARGXStyle::Professional)
230 {
231 for (const auto &x : this->options)
232 {
233 // Main option header line
234 contentStr += "ID: " + x.id + "\n";
235 contentStr += "[ " + x.sparam + " | " + x.param;
236
237 if (x.hasSubParams && !x.subParams.empty())
238 {
239 contentStr += " [ ";
240
241 for (size_t i = 0; i < x.subParams.size(); ++i)
242 {
243 const auto &sub = x.subParams[i];
244
245 contentStr += sub.param;
246
247 if (i < x.subParams.size() - 1) contentStr += " | ";
248 else if (i <= x.subParams.size()) contentStr += ' ';
249 }
250
251 contentStr += "] ] ";
252 }
253
254 else contentStr += " ] ";
255
256 contentStr += x.info + "\n";
257
258 // Print all sub-options with sparam and param, aligned with ideographic spaces if there are
259 if (x.hasSubParams && !x.subParams.empty())
260 {
261 for (const auto &sub : x.subParams)
262 {
263 // Create ideographic spaces matching the length of main param for alignment
264 std::wstring wideSpaces(x.param.size(), L'\u3000');
265 std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
266 std::string spacing = converter.to_bytes(wideSpaces);
267
268 contentStr += spacing + " [ " + sub.sparam + " | " + sub.param + " ] " + sub.info + "\n";
269 }
270 }
271 }
272 }
273
274 else if (style == ARGXStyle::Simple)
275 {
276 for (const auto &x : this->options)
277 {
278 contentStr += x.sparam + ", " + x.param + " - " + x.info + "\n";
279
280 if (x.hasSubParams && !x.subParams.empty())
281 {
282 for (const auto &sub : x.subParams)
283 {
284 contentStr += " " + sub.sparam + ", " + sub.param + " - " + sub.info + "\n";
285 }
286 }
287 }
288 } // ARGXStyle
289
290 return title + "\n" + mainInfo + "\n" + contentStr;
291 }
292
293 bool Argx::compareArgs(std::vector<ARGXOptions> options, std::vector<std::string> argv)
294 {
295 // Skip program name ( as arg )
296 for (size_t i = 1 ; i < argv.size() ; ++i)
297 {
298 const std::string &arg = argv[i];
299
300 bool found = false;
301 for (const auto &option : options)
302 {
303 if (option.sparam == arg || option.param == arg)
304 {
305 found = true;
306 break;
307 }
308 }
309 if (!found)
310 {
311 return false; // Unknown argument
312 }
313 }
314 return true; // All arguments are valid
315 }
316
317 std::vector<std::string> Argx::getMainArgs() const
318 { return *this->mainArgs; }
319
320 int Argx::getArgc() const
321 { return this->mainArgc; }
322
323 std::vector<ARGXOptions> Argx::getOptions() const
324 { return this->options; }
325
326 std::string Argx::getID() const
327 { return this->id; }
328}
329
ARGXParam getParam(const std::string &id)
Get the param from id
Definition Argx.cpp:103
static unsigned int mainArgc
Definition Argx.hpp:25
std::vector< ARGXOptions > getOptions() const
Get main set options as ARGXOptions.
Definition Argx.cpp:323
static std::vector< std::string > * mainArgs
Definition Argx.hpp:23
std::vector< std::string > getMainArgs() const
Get main arguments from main() function argv
Definition Argx.cpp:317
std::string getID() const
Get Argx ID.
Definition Argx.cpp:326
int getArgc() const
Get the main options from the main() function as argc.
Definition Argx.cpp:320
bool paramExists(const std::string &id)
Get if param exists in the param options.
Definition Argx.cpp:94
int findParam(const std::string &id)
Find parameter index.
Definition Argx.cpp:48
std::string createDocs(ARGXStyle style, const std::string &title, const std::string &mainInfo)
Create documentation for the parameters with the specific style, title and main information.
Definition Argx.cpp:225
void add(ARGXOptions option) const
Add param options.
Definition Argx.cpp:38
static std::vector< ARGXOptions > options
Definition Argx.hpp:22
bool compareArgs(std::vector< ARGXOptions > options, std::vector< std::string > argv)
Compare if options contains the required id, if the ID does not exist, return false.
Definition Argx.cpp:293
bool getSubParam(const argx::ARGXParam &param, const std::string &id)
Get the sub-param from id
Definition Argx.cpp:222
std::string id
Definition Argx.hpp:20
Definition Argx.hpp:16
ARGXStyle
Definition types.hpp:10
std::vector< bool > subExists
Definition types.hpp:51