CommandLineParser.hpp
Go to the documentation of this file.
1 /*
2 
3  This file is part of OpenFLUID software
4  Copyright(c) 2007, INRA - Montpellier SupAgro
5 
6 
7  == GNU General Public License Usage ==
8 
9  OpenFLUID is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  OpenFLUID is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with OpenFLUID. If not, see <http://www.gnu.org/licenses/>.
21 
22 
23  == Other Usage ==
24 
25  Other Usage means a use of OpenFLUID that is inconsistent with the GPL
26  license, and requires a written agreement between You and INRA.
27  Licensees for Other Usage of OpenFLUID may use this file in accordance
28  with the terms contained in the written agreement between You and INRA.
29 
30 */
31 
32 /**
33  @file CommandLineParser.hpp
34 
35  @author Jean-Christophe FABRE <jean-christophe.fabre@supagro.inra.fr>
36 */
37 
38 
39 #ifndef __OPENFLUID_UTILS_COMMANDLINEPARSER_HPP__
40 #define __OPENFLUID_UTILS_COMMANDLINEPARSER_HPP__
41 
42 
43 #include <map>
44 #include <string>
45 #include <ostream>
46 
47 
48 namespace openfluid { namespace utils {
49 
50 
52 {
53  private:
54 
55  std::string m_LongName;
56 
57  std::string m_ShortName;
58 
59  bool m_ValueRequired;
60 
61  std::string m_Value;
62 
63  std::string m_HelpText;
64 
65  bool m_Active;
66 
67 
68  public:
69 
71  m_ValueRequired(false),m_Active(false)
72  { }
73 
74 
75  // =====================================================================
76  // =====================================================================
77 
78 
79  CommandLineOption(const std::string& LongName, const std::string& ShortName,
80  const std::string& HelpText, bool ValueRequired = false):
81  m_LongName(LongName),m_ShortName(ShortName), m_ValueRequired(ValueRequired), m_HelpText(HelpText),
82  m_Active(false)
83  { }
84 
85 
86  // =====================================================================
87  // =====================================================================
88 
89 
90  std::string getHelpText() const
91  { return m_HelpText; }
92 
93 
94  // =====================================================================
95  // =====================================================================
96 
97 
98  std::string getLongName() const
99  { return m_LongName; }
100 
101 
102  // =====================================================================
103  // =====================================================================
104 
105 
106  std::string getShortName() const
107  { return m_ShortName; }
108 
109 
110  // =====================================================================
111  // =====================================================================
112 
113 
114  std::string getValue() const
115  { return m_Value; }
116 
117 
118  // =====================================================================
119  // =====================================================================
120 
121 
122  bool isActive() const
123  { return m_Active; }
124 
125 
126  // =====================================================================
127  // =====================================================================
128 
129 
130  bool isValueRequired() const
131  { return m_ValueRequired; }
132 
133 
134  // =====================================================================
135  // =====================================================================
136 
137 
138  void activate(const std::string& Value = "")
139  {
140  m_Value = Value;
141 
142  if ((!m_ValueRequired) || (m_ValueRequired && !m_Value.empty()))
143  m_Active = true;
144  else
145  m_Active = false;
146  }
147 
148 
149  // =====================================================================
150  // =====================================================================
151 
152 
153  void reset()
154  {
155  m_Active = false;
156  m_Value = "";
157  }
158 
159 };
160 
161 
162 // =====================================================================
163 // =====================================================================
164 
165 
167 {
168  private:
169 
170  std::string m_Name;
171 
172  std::string m_HelpText;
173 
174  std::map<std::string,CommandLineOption> m_Options;
175 
176  std::map<std::string,CommandLineOption*> m_ShortOptions;
177 
178 
179  public:
180 
182  { }
183 
184 
185  // =====================================================================
186  // =====================================================================
187 
188 
189  CommandLineCommand(const std::string& Name, const std::string& HelpText):
190  m_Name(Name), m_HelpText(HelpText)
191  { }
192 
193 
194  // =====================================================================
195  // =====================================================================
196 
197 
198  std::string getHelpText() const
199  { return m_HelpText; }
200 
201 
202  // =====================================================================
203  // =====================================================================
204 
205 
206  std::string getName() const
207  { return m_Name; }
208 
209 
210  // =====================================================================
211  // =====================================================================
212 
213 
214  const std::map<std::string,CommandLineOption>& options()
215  { return m_Options; }
216 
217 
218  // =====================================================================
219  // =====================================================================
220 
221 
222  void addOption(const CommandLineOption& Option)
223  {
224  m_Options[Option.getLongName()] = Option;
225 
226  if (!Option.getShortName().empty())
227  m_ShortOptions[Option.getShortName()] = &m_Options[Option.getLongName()];
228  }
229 
230 
231  // =====================================================================
232  // =====================================================================
233 
234 
235  bool activateOption(const std::string& LongName, const std::string& Value = "")
236  {
237  auto it = m_Options.find(LongName);
238 
239  if (it == m_Options.end())
240  return false;
241 
242  (*it).second.activate(Value);
243  return (*it).second.isActive();
244  }
245 
246 
247  // =====================================================================
248  // =====================================================================
249 
250 
251  std::string getOptionNameFromShortName(const std::string& ShortName) const
252  {
253  auto it = m_ShortOptions.find(ShortName);
254 
255  if (it == m_ShortOptions.end())
256  return "";
257 
258  return (*it).second->getLongName();
259  }
260 
261 
262  // =====================================================================
263  // =====================================================================
264 
265 
266  bool isOptionExists(const std::string& LongName) const
267  {
268  return (m_Options.find(LongName) != m_Options.end());
269  }
270 
271 
272  // =====================================================================
273  // =====================================================================
274 
275 
276  bool isOptionRequiresValue(const std::string& LongName) const
277  {
278  auto it = m_Options.find(LongName);
279 
280  if (it == m_Options.end())
281  return false;
282 
283  return (*it).second.isValueRequired();
284 
285  }
286 
287 
288  // =====================================================================
289  // =====================================================================
290 
291 
292  bool isOptionActive(const std::string& LongName) const
293  {
294  auto it = m_Options.find(LongName);
295 
296  return (it != m_Options.end() && (*it).second.isActive());
297  }
298 
299 
300  // =====================================================================
301  // =====================================================================
302 
303 
304  std::string getOptionValue(const std::string& LongName) const
305  {
306  auto it = m_Options.find(LongName);
307 
308  if (it == m_Options.end())
309  return "";
310 
311  return ((*it).second.getValue());
312  }
313 
314 
315  // =====================================================================
316  // =====================================================================
317 
318 
319  void reset()
320  {
321  for (auto& Opt : m_Options)
322  Opt.second.reset();
323  }
324 
325 };
326 
327 
328 // =====================================================================
329 // =====================================================================
330 
331 
333 {
334  private:
335 
336  std::string m_ProgramName;
337 
338  std::string m_HelpText;
339 
340  std::map<std::string,CommandLineCommand> m_Commands;
341 
342  std::string m_ActiveCommand;
343 
344  std::vector<std::string> m_ExtraArgs;
345 
346  std::string m_ParsingMessage;
347 
348  bool m_HelpAsked;
349 
350 
351  public:
352 
354  m_HelpAsked(false)
355  {
356  addCommand(CommandLineCommand("",""));
357  }
358 
359 
360  // =====================================================================
361  // =====================================================================
362 
363 
364  CommandLineParser(const std::string& ProgramName, const std::string& HelpText) :
365  m_ProgramName(ProgramName), m_HelpText(HelpText), m_HelpAsked(false)
366  {
367  addCommand(CommandLineCommand("",""));
368  }
369 
370 
371  // =====================================================================
372  // =====================================================================
373 
374 
375  const std::vector<std::string>& extraArgs() const
376  { return m_ExtraArgs; }
377 
378 
379  // =====================================================================
380  // =====================================================================
381 
382 
383  std::string getHelpText() const
384  { return m_HelpText; }
385 
386 
387  // =====================================================================
388  // =====================================================================
389 
390 
391  std::string getProgramName() const
392  { return m_ProgramName; }
393 
394 
395  // =====================================================================
396  // =====================================================================
397 
398 
399  std::string getParsingMessage() const
400  { return m_ParsingMessage; }
401 
402 
403  // =====================================================================
404  // =====================================================================
405 
406 
407  std::string getActiveCommand() const
408  { return m_ActiveCommand; }
409 
410 
411  // =====================================================================
412  // =====================================================================
413 
414 
415  const CommandLineCommand& command(const std::string& Name) const
416  {
417  return m_Commands.at(Name);
418  }
419 
420 
421  // =====================================================================
422  // =====================================================================
423 
424 
425  void addCommand(const CommandLineCommand& Command)
426  {
427  m_Commands[Command.getName()] = Command;
428  }
429 
430  // =====================================================================
431  // =====================================================================
432 
433 
434  void addOption(const CommandLineOption& Option)
435  {
436  m_Commands[""].addOption(Option);
437  }
438 
439 
440  // =====================================================================
441  // =====================================================================
442 
443 
444  bool parse(std::list<std::string> ArgValues)
445  {
446  reset();
447 
448  while (!ArgValues.empty())
449  {
450  std::string Arg = ArgValues.front();
451  ArgValues.pop_front();
452 
453  if (Arg[0] != '-')
454  {
455  // arg not an option
456  if (m_ActiveCommand.empty())
457  m_ActiveCommand = Arg;
458  else
459  m_ExtraArgs.push_back(Arg);
460  }
461  else
462  {
463  // arg is an option
464 
465  // check if the command exists
466  auto it = m_Commands.find(m_ActiveCommand);
467  if (it == m_Commands.end())
468  {
469  m_ParsingMessage = "unknown \""+ m_ActiveCommand + "\" command";
470  return false;
471  }
472 
473  if (Arg == "-h" || Arg == "--help")
474  m_HelpAsked = true;
475  else if (Arg.size() < 2)
476  {
477  m_ParsingMessage = "wrong format for option \"" + Arg + "\"";
478  return false;
479  }
480  else
481  {
482  std::string LongOptName;
483  std::string OptValue;
484  bool IsFromShort = false;
485 
486  if (Arg[1] != '-')
487  {
488  if (Arg.size() != 2)
489  {
490  m_ParsingMessage = "wrong format for short option \"" + Arg + "\"";
491  return false;
492  }
493 
494  // short option
495  LongOptName = m_Commands[m_ActiveCommand].getOptionNameFromShortName(Arg.substr(1,1));
496  IsFromShort = true;
497  }
498  else
499  {
500  // long option
501  std::string TmpName = Arg.substr(2,Arg.size()-2);
502 
503  std::string::size_type EqualPos = TmpName.find("=");
504 
505  if (EqualPos != std::string::npos)
506  {
507  LongOptName = TmpName.substr(0,EqualPos);
508  OptValue = TmpName.substr(EqualPos+1,TmpName.size()-EqualPos-1);
509  }
510  else
511  LongOptName = TmpName;
512  }
513 
514  if (!m_Commands[m_ActiveCommand].isOptionExists(LongOptName))
515  {
516  // unknown option
517  m_ParsingMessage = "unknown option \"" + Arg + "\"";
518  if (!m_ActiveCommand.empty())
519  m_ParsingMessage += " for command \"" + m_ActiveCommand + "\"";
520  return false;
521  }
522 
523  if (m_Commands[m_ActiveCommand].isOptionRequiresValue(LongOptName))
524  {
525  if (IsFromShort && !ArgValues.empty())
526  {
527  OptValue = ArgValues.front();
528  ArgValues.pop_front();
529  }
530 
531  if (OptValue.empty())
532  {
533  m_ParsingMessage = "missing value for option \"" + Arg + "\"";
534  return false;
535  }
536  }
537 
538  if (!m_Commands[m_ActiveCommand].activateOption(LongOptName,OptValue))
539  {
540  // wrong option format
541  m_ParsingMessage = "unknown error for option \"" + Arg + "\"";
542  return false;
543  }
544  }
545  }
546  }
547  return true;
548  }
549 
550 
551  // =====================================================================
552  // =====================================================================
553 
554 
555  bool parse(int ArgC, char **ArgV)
556  {
557  std::list<std::string> ArgValues;
558 
559  for (int i=1; i< ArgC; i++)
560  ArgValues.push_back(std::string(ArgV[i]));
561 
562  return parse(ArgValues);
563  }
564 
565 
566  // =====================================================================
567  // =====================================================================
568 
569 
570  void reset()
571  {
572  m_ActiveCommand.clear();
573  m_ParsingMessage.clear();
574  m_ExtraArgs.clear();
575 
576  for (auto& Cmd : m_Commands)
577  Cmd.second.reset();
578  }
579 
580 
581  // =====================================================================
582  // =====================================================================
583 
584 
585  bool isHelpAsked()
586  { return m_HelpAsked; }
587 
588 
589  // =====================================================================
590  // =====================================================================
591 
592 
593  void printHelp(std::ostream& OutStm)
594  {
595  std::string m_CmdName = m_ActiveCommand;
596  if (m_CmdName.empty())
597  m_CmdName = "[<command>]";
598 
599  OutStm << "Usage : " << m_ProgramName << " " << m_CmdName << " [<options>] [<args>]\n";
600 
601  if (m_ActiveCommand.empty())
602  {
603  OutStm << "\nAvailable commands:\n";
604 
605  for (auto& Cmd : m_Commands)
606  if (!Cmd.first.empty())
607  OutStm << " " << Cmd.first << " : " << Cmd.second.getHelpText() << "\n";
608  }
609 
610  if (!m_Commands[m_ActiveCommand].getHelpText().empty())
611  OutStm << "\n" << m_Commands[m_ActiveCommand].getHelpText() << "\n";
612 
613  OutStm << "\nAvailable options:\n";
614  OutStm << " --help,-h : display this help message\n";
615 
616  for (auto& Opt : m_Commands[m_ActiveCommand].options())
617  {
618  OutStm << " --" << Opt.second.getLongName();
619  if (Opt.second.isValueRequired())
620  OutStm << "=<arg>";
621 
622  if (!Opt.second.getShortName().empty())
623  {
624  OutStm << ", -" << Opt.second.getShortName();
625  if (Opt.second.isValueRequired())
626  OutStm << " <arg>";
627  }
628 
629  OutStm << " : " << Opt.second.getHelpText() << "\n";
630  }
631  }
632 
633 
634  // =====================================================================
635  // =====================================================================
636 
637 
638  void printState(std::ostream& OutStm)
639  {
640  for (auto& Cmd : m_Commands)
641  {
642  if (!Cmd.first.empty())
643  {
644  if (Cmd.first == m_ActiveCommand)
645  OutStm << "+";
646  else OutStm << "-";
647 
648  OutStm << " " << Cmd.first << " : " << Cmd.second.getHelpText() << "\n";
649 
650  for (auto& Opt : Cmd.second.options())
651  {
652  OutStm << " ";
653 
654  if (Opt.second.isActive())
655  OutStm << "+";
656  else
657  OutStm << "-";
658  OutStm << " " << Opt.first;
659 
660  if (!Opt.second.getShortName().empty())
661  OutStm << "," << Opt.second.getShortName();
662 
663  if (Opt.second.isValueRequired())
664  OutStm << "[" << Opt.second.getValue() << "]";
665 
666  OutStm << " : " << Opt.second.getHelpText() << "\n";
667  }
668  }
669  }
670 
671 
672  if (!m_ExtraArgs.empty())
673  {
674  OutStm << "Extra arguments :";
675  for (auto& Arg : m_ExtraArgs)
676  OutStm << " " << Arg;
677  OutStm << "\n";
678  }
679 
680  }
681 
682 };
683 
684 
685 
686 } }
687 
688 
689 #endif /* __OPENFLUID_UTILS_COMMANDLINEPARSER_HPP__ */
void reset()
Definition: CommandLineParser.hpp:319
bool isHelpAsked()
Definition: CommandLineParser.hpp:585
void printState(std::ostream &OutStm)
Definition: CommandLineParser.hpp:638
bool isValueRequired() const
Definition: CommandLineParser.hpp:130
Definition: CommandLineParser.hpp:332
std::string getParsingMessage() const
Definition: CommandLineParser.hpp:399
std::string getHelpText() const
Definition: CommandLineParser.hpp:383
std::string getValue() const
Definition: CommandLineParser.hpp:114
bool isOptionActive(const std::string &LongName) const
Definition: CommandLineParser.hpp:292
std::string getName() const
Definition: CommandLineParser.hpp:206
std::string getLongName() const
Definition: CommandLineParser.hpp:98
void reset()
Definition: CommandLineParser.hpp:153
CommandLineOption()
Definition: CommandLineParser.hpp:70
CommandLineParser()
Definition: CommandLineParser.hpp:353
bool isOptionExists(const std::string &LongName) const
Definition: CommandLineParser.hpp:266
void addCommand(const CommandLineCommand &Command)
Definition: CommandLineParser.hpp:425
Definition: CommandLineParser.hpp:51
void addOption(const CommandLineOption &Option)
Definition: CommandLineParser.hpp:222
void printHelp(std::ostream &OutStm)
Definition: CommandLineParser.hpp:593
bool parse(int ArgC, char **ArgV)
Definition: CommandLineParser.hpp:555
const std::vector< std::string > & extraArgs() const
Definition: CommandLineParser.hpp:375
void addOption(const CommandLineOption &Option)
Definition: CommandLineParser.hpp:434
CommandLineParser(const std::string &ProgramName, const std::string &HelpText)
Definition: CommandLineParser.hpp:364
bool parse(std::list< std::string > ArgValues)
Definition: CommandLineParser.hpp:444
std::string getProgramName() const
Definition: CommandLineParser.hpp:391
CommandLineCommand()
Definition: CommandLineParser.hpp:181
std::string getOptionNameFromShortName(const std::string &ShortName) const
Definition: CommandLineParser.hpp:251
Definition: CommandLineParser.hpp:166
const std::map< std::string, CommandLineOption > & options()
Definition: CommandLineParser.hpp:214
Definition: ApplicationException.hpp:47
void reset()
Definition: CommandLineParser.hpp:570
void activate(const std::string &Value="")
Definition: CommandLineParser.hpp:138
CommandLineOption(const std::string &LongName, const std::string &ShortName, const std::string &HelpText, bool ValueRequired=false)
Definition: CommandLineParser.hpp:79
std::string getActiveCommand() const
Definition: CommandLineParser.hpp:407
std::string getShortName() const
Definition: CommandLineParser.hpp:106
bool isActive() const
Definition: CommandLineParser.hpp:122
std::string getOptionValue(const std::string &LongName) const
Definition: CommandLineParser.hpp:304
std::string getHelpText() const
Definition: CommandLineParser.hpp:198
bool isOptionRequiresValue(const std::string &LongName) const
Definition: CommandLineParser.hpp:276
std::string getHelpText() const
Definition: CommandLineParser.hpp:90
bool activateOption(const std::string &LongName, const std::string &Value="")
Definition: CommandLineParser.hpp:235
CommandLineCommand(const std::string &Name, const std::string &HelpText)
Definition: CommandLineParser.hpp:189
const CommandLineCommand & command(const std::string &Name) const
Definition: CommandLineParser.hpp:415