FreeNOS
ArgumentParser.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 Niek Linnenbank
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ArgumentParser.h"
19#include "ConstHashIterator.h"
20
22{
23 m_name = "PROGNAME";
24 m_description = "program description";
25}
26
28{
29 // cleanup flags
31 it.hasCurrent();)
32 {
33 delete it.current();
34 it.remove();
35 }
36
37 // cleanup positionals
38 for (Size i = 0; i < m_positionals.count(); i++)
39 delete m_positionals[i];
40}
41
43{
45
46 // Build the syntax line
47 usage << "usage: " << *m_name << " [OPTIONS] ";
48
49 // Append positional arguments to syntax line
50 for (Size i = 0; i < m_positionals.count(); i++)
51 {
52 if (m_positionals[i]->getCount() == 0)
53 usage << "[" << m_positionals[i]->getName() << "..] ";
54 else
55 usage << m_positionals[i]->getName() << " ";
56 }
57 // Append description
58 usage << "\r\n\r\n" << *m_description << "\r\n";
59
60 if (m_positionals.count() > 0)
61 usage << "\r\n Positional Arguments:\r\n\r\n";
62
63 // Make list of positional arguments
64 for (Size i = 0; i < m_positionals.count(); i++)
65 {
66 (usage << " " << m_positionals[i]->getName()).pad(16) <<
67 " " << m_positionals[i]->getDescription() << "\r\n";
68 }
69
70 // Make list of flag arguments
71 if (m_flags.count() > 0)
72 usage << "\r\n Optional Arguments:\r\n\r\n";
73
75 it.hasCurrent(); it++)
76 {
77 char tmp[2] = { it.current()->getIdentifier(), 0 };
78
79 (usage << " -" << tmp << ", --" << it.current()->getName()).pad(16) <<
80 " " << it.current()->getDescription() << "\r\n";
81 }
82 return usage;
83}
84
86{
87 return m_name;
88}
89
90void ArgumentParser::setName(const char *name)
91{
92 m_name = name;
93}
94
96{
97 m_description = desc;
98}
99
101 const char *name,
102 const char *description)
103{
104 // Insert the flag by its full name
105 Argument *arg = new Argument(name);
106 arg->setDescription(description);
107 arg->setIdentifier(id);
108 m_flags.insert(name, arg);
109
110 // Also insert the flag using its single character identifier
111 char tmp[2];
112 tmp[0] = id;
113 tmp[1] = 0;
114
115 m_flagsId.insert(tmp, arg);
116 return Success;
117}
118
120 const char *description,
121 Size count)
122{
123 // Check that only the last positional can have count zero.
124 if (m_positionals.count() &&
126 {
127 return AlreadyExists;
128 }
129 Argument *arg = new Argument(name);
130 arg->setDescription(description);
131 arg->setCount(count);
133 return Success;
134}
135
137 char **argv,
138 ArgumentContainer & output)
139{
140 Size pos = 0;
141 Size i = 0;
142
143 if (argc <= 0)
144 return InvalidArgument;
145
146 for (int i = 1; i < argc; i++)
147 {
148 String str = argv[i];
149 List<String> parts = str.split('=');
150 String & part1 = parts[0];
151 String argname;
152 Argument * const *arg;
153 Argument *outarg;
154
155 // Is this a flag based argument in full form? (e.g.: --arg)
156 if (part1.length() > 1 && part1[0] == '-' && part1[1] == '-')
157 {
158 argname = part1.substring(2);
159
160 // Flag must exist
161 arg = m_flags.get(*argname);
162 if (!arg)
163 {
164 arg = m_flagsId.get(*argname);
165 if (!arg)
166 return InvalidArgument;
167 }
168
169 outarg = new Argument((*arg)->getName());
170 outarg->setValue(*parts.last());
171 output.addFlag(outarg);
172 }
173 // Flag based argument in short form? (e.g.: -a or a list: -abc)
174 else if (part1.length() > 1 && part1[0] == '-' && part1[1] != '-')
175 {
176 // Loop all supplied short form arguments
177 for (Size i = 1; i < part1.length(); i++)
178 {
179 char tmp[2];
180 tmp[0] = part1[i];
181 tmp[1] = 0;
182
183 // Flag must exist
184 arg = m_flags.get(tmp);
185 if (!arg)
186 {
187 arg = m_flagsId.get(tmp);
188 if (!arg)
189 return InvalidArgument;
190 }
191
192 outarg = new Argument((*arg)->getName());
193 outarg->setValue(*parts.last());
194 output.addFlag(outarg);
195 }
196 }
197 // Positional argument
198 else if (m_positionals.count() > 0)
199 {
200 if (pos > m_positionals.count() - 1)
201 return InvalidArgument;
202
203 if (m_positionals[pos]->getCount() == 0)
204 outarg = new Argument(*part1);
205 else
206 outarg = new Argument(*m_positionals[pos++]->getName());
207
208 outarg->setValue(*parts.last());
209 output.addPositional(outarg);
210 }
211 else return InvalidArgument;
212 }
213 // Check that all required arguments are set
214 for (i = 0; i < m_positionals.count(); i++)
215 {
216 if (m_positionals[i]->getCount() == 0)
217 break;
218 }
219 if (output.getPositionals().count() >= i)
220 return Success;
221 else
222 return NotFound;
223}
void usage(char *prog)
Definition LinnDump.cpp:52
Generic command-line argument parser.
Result addPositional(Argument *arg)
Add positional argument.
const Vector< Argument * > & getPositionals() const
Get positional arguments.
Result addFlag(Argument *arg)
Add flag argument.
Result
Result codes.
void setDescription(const String &desc)
Set program description.
Result registerPositional(const char *name, const char *description, Size count=1)
Register a positional argument.
String getUsage() const
Get program usage.
String m_name
Program name.
const String & name() const
Retrieve program name.
Vector< Argument * > m_positionals
Contains all registered positional arguments.
HashTable< String, Argument * > m_flags
Contains all registered flag arguments by name.
String m_description
Program description.
Result parse(int argc, char **argv, ArgumentContainer &output)
Parse input arguments.
HashTable< String, Argument * > m_flagsId
Contains all registered flag arguments by single character identifier.
void setName(const char *name)
Set program name.
virtual ~ArgumentParser()
Destructor.
Result registerFlag(char arg, const char *name, const char *description)
Register a flag Argument.
ArgumentParser()
Constructor.
Represents program command line argument.
Definition Argument.h:36
void setCount(Size count)
Set argument maximum count.
Definition Argument.cpp:79
void setIdentifier(char id)
Set argument identifier.
Definition Argument.cpp:59
void setDescription(const char *description)
Set argument single line description.
Definition Argument.cpp:69
Size getCount() const
Retrieve maximum argument count (if set)
Definition Argument.cpp:39
void setValue(const char *value)
Set argument option value.
Definition Argument.cpp:74
Iterate through a constant (read-only) HashTable.
virtual bool hasCurrent() const
Check if there is a current item.
Iterate through a HashTable.
virtual bool hasCurrent() const
Check if there is a current item.
virtual const V * get(const K &key) const
Returns the first value for the given key.
Definition HashTable.h:287
virtual Size count() const
Get the number of values stored in the HashTable.
Definition HashTable.h:211
virtual bool insert(const K &key, const V &value)
Inserts the given item to the HashTable.
Definition HashTable.h:133
Simple linked list template class.
Definition List.h:37
T last()
Get the last value on the list.
Definition List.h:316
virtual int remove(T value)
Remove all items with the given value.
Definition Sequence.h:88
Abstraction of strings.
Definition String.h:42
String substring(const Size index, const Size size=0) const
Returns a part of the String as a copy.
Definition String.cpp:314
Size length() const
Same as count().
Definition String.cpp:105
List< String > split(const char delimiter) const
Split the String into parts separated by a delimiter.
Definition String.cpp:408
virtual const T & at(Size position) const
Return item at the given position as a reference.
Definition Vector.h:153
virtual int insert(const T &item)
Adds the given item to the Vector, if possible.
Definition Vector.h:93
virtual Size count() const
Returns the number of items inside the Vector.
Definition Vector.h:204
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128