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 {
44  String usage;
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 
90 void 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);
132  m_positionals.insert(arg);
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 }
ArgumentParser::Result
Result
Result codes.
Definition: ArgumentParser.h:47
ConstHashIterator::hasCurrent
virtual bool hasCurrent() const
Check if there is a current item.
Definition: ConstHashIterator.h:82
String::length
Size length() const
Same as count().
Definition: String.cpp:105
ArgumentParser::m_name
String m_name
Program name.
Definition: ArgumentParser.h:149
Vector::at
virtual const T & at(Size position) const
Return item at the given position as a reference.
Definition: Vector.h:153
String
Abstraction of strings.
Definition: String.h:41
HashIterator
Iterate through a HashTable.
Definition: HashIterator.h:39
ArgumentParser::m_description
String m_description
Program description.
Definition: ArgumentParser.h:152
ArgumentParser::NotFound
@ NotFound
Definition: ArgumentParser.h:51
Argument::setCount
void setCount(Size count)
Set argument maximum count.
Definition: Argument.cpp:79
ArgumentParser::setDescription
void setDescription(const String &desc)
Set program description.
Definition: ArgumentParser.cpp:95
ArgumentParser::m_flags
HashTable< String, Argument * > m_flags
Contains all registered flag arguments by name.
Definition: ArgumentParser.h:140
ArgumentParser::ArgumentParser
ArgumentParser()
Constructor.
Definition: ArgumentParser.cpp:21
String::split
List< String > split(const char delimiter) const
Split the String into parts separated by a delimiter.
Definition: String.cpp:408
ArgumentContainer
Generic command-line argument parser.
Definition: ArgumentContainer.h:40
Argument
Represents program command line argument.
Definition: Argument.h:35
ArgumentContainer::addPositional
Result addPositional(Argument *arg)
Add positional argument.
Definition: ArgumentContainer.cpp:67
ArgumentParser::InvalidArgument
@ InvalidArgument
Definition: ArgumentParser.h:50
HashTable::get
virtual const V * get(const K &key) const
Returns the first value for the given key.
Definition: HashTable.h:287
Argument::getCount
Size getCount() const
Retrieve maximum argument count (if set)
Definition: Argument.cpp:39
ArgumentParser::~ArgumentParser
virtual ~ArgumentParser()
Destructor.
Definition: ArgumentParser.cpp:27
usage
void usage(char *prog)
Definition: LinnDump.cpp:52
HashTable::count
virtual Size count() const
Get the number of values stored in the HashTable.
Definition: HashTable.h:211
Vector::count
virtual Size count() const
Returns the number of items inside the Vector.
Definition: Vector.h:204
ArgumentParser::m_positionals
Vector< Argument * > m_positionals
Contains all registered positional arguments.
Definition: ArgumentParser.h:146
ArgumentParser::AlreadyExists
@ AlreadyExists
Definition: ArgumentParser.h:52
ArgumentParser::Success
@ Success
Definition: ArgumentParser.h:49
Argument::setValue
void setValue(const char *value)
Set argument option value.
Definition: Argument.cpp:74
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
ArgumentParser::registerFlag
Result registerFlag(char arg, const char *name, const char *description)
Register a flag Argument.
Definition: ArgumentParser.cpp:100
Argument::setDescription
void setDescription(const char *description)
Set argument single line description.
Definition: Argument.cpp:69
ArgumentParser::name
const String & name() const
Retrieve program name.
Definition: ArgumentParser.cpp:85
Vector::insert
virtual int insert(const T &item)
Adds the given item to the Vector, if possible.
Definition: Vector.h:93
ConstHashIterator.h
ArgumentParser::m_flagsId
HashTable< String, Argument * > m_flagsId
Contains all registered flag arguments by single character identifier.
Definition: ArgumentParser.h:143
String::substring
String substring(const Size index, const Size size=0) const
Returns a part of the String as a copy.
Definition: String.cpp:314
ArgumentParser::registerPositional
Result registerPositional(const char *name, const char *description, Size count=1)
Register a positional argument.
Definition: ArgumentParser.cpp:119
ArgumentParser.h
ArgumentContainer::addFlag
Result addFlag(Argument *arg)
Add flag argument.
Definition: ArgumentContainer.cpp:73
HashIterator::hasCurrent
virtual bool hasCurrent() const
Check if there is a current item.
Definition: HashIterator.h:83
List< String >
Argument::setIdentifier
void setIdentifier(char id)
Set argument identifier.
Definition: Argument.cpp:59
ArgumentParser::getUsage
String getUsage() const
Get program usage.
Definition: ArgumentParser.cpp:42
ConstHashIterator
Iterate through a constant (read-only) HashTable.
Definition: ConstHashIterator.h:39
HashTable::insert
virtual bool insert(const K &key, const V &value)
Inserts the given item to the HashTable.
Definition: HashTable.h:133
ArgumentParser::setName
void setName(const char *name)
Set program name.
Definition: ArgumentParser.cpp:90
List::last
T last()
Get the last value on the list.
Definition: List.h:316
ArgumentContainer::getPositionals
const Vector< Argument * > & getPositionals() const
Get positional arguments.
Definition: ArgumentContainer.cpp:39
ArgumentParser::parse
Result parse(int argc, char **argv, ArgumentContainer &output)
Parse input arguments.
Definition: ArgumentParser.cpp:136