Manual for OpenFLUID 2.1.10

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@inra.fr>
36 */
37 
38 
39 #ifndef __OPENFLUID_UTILS_COMMANDLINEPARSER_HPP__
40 #define __OPENFLUID_UTILS_COMMANDLINEPARSER_HPP__
41 
42 
43 #include <map>
44 #include <vector>
45 #include <list>
46 #include <string>
47 #include <ostream>
48 
49 
50 namespace openfluid { namespace utils {
51 
52 
54 {
55  private:
56 
57  std::string m_LongName;
58 
59  std::string m_ShortName;
60 
61  bool m_ValueRequired;
62 
63  std::string m_Value;
64 
65  std::string m_HelpText;
66 
67  bool m_Active;
68 
69 
70  public:
71 
73  m_ValueRequired(false),m_Active(false)
74  { }
75 
76 
77  // =====================================================================
78  // =====================================================================
79 
80 
81  /**
82  Instanciates an option with the given parameters
83  @param[in] LongName The long name of the option
84  @param[in] ShortName The short name of the option
85  @param[in] HelpText The help text associated to the option
86  @param[in] ValueRequired Set to true to require a value with this option (default is false)
87  */
88  CommandLineOption(const std::string& LongName, const std::string& ShortName,
89  const std::string& HelpText, bool ValueRequired = false):
90  m_LongName(LongName),m_ShortName(ShortName), m_ValueRequired(ValueRequired), m_HelpText(HelpText),
91  m_Active(false)
92  { }
93 
94 
95  // =====================================================================
96  // =====================================================================
97 
98 
99  /**
100  Returns the help text of the option
101  @return The help text
102  */
103  std::string getHelpText() const
104  {
105  return m_HelpText;
106  }
107 
108 
109  // =====================================================================
110  // =====================================================================
111 
112 
113  /**
114  Returns the long name of the option (e.g. 'output-dir')
115  @return The long name
116  */
117  std::string getLongName() const
118  {
119  return m_LongName;
120  }
121 
122 
123  // =====================================================================
124  // =====================================================================
125 
126 
127  /**
128  Returns the short name of the option (e.g. 'o')
129  @return The short name
130  */
131  std::string getShortName() const
132  {
133  return m_ShortName;
134  }
135 
136 
137  // =====================================================================
138  // =====================================================================
139 
140 
141  /**
142  Returns the value of the option
143  @return The value
144  */
145  std::string getValue() const
146  {
147  return m_Value;
148  }
149 
150 
151  // =====================================================================
152  // =====================================================================
153 
154 
155  /**
156  Tests if the option is active
157  @return true if the option is active
158  */
159  bool isActive() const
160  {
161  return m_Active;
162  }
163 
164 
165  // =====================================================================
166  // =====================================================================
167 
168 
169  /**
170  Tests if the option requires a value
171  @return true if the option requires a value
172  */
173  bool isValueRequired() const
174  {
175  return m_ValueRequired;
176  }
177 
178 
179  // =====================================================================
180  // =====================================================================
181 
182 
183  /**
184  Activates the option with the given value
185  @param[in] Value The value for activation (default is empty)
186  */
187  void activate(const std::string& Value = "")
188  {
189  m_Value = Value;
190 
191  if ((!m_ValueRequired) || (m_ValueRequired && !m_Value.empty()))
192  {
193  m_Active = true;
194  }
195  else
196  {
197  m_Active = false;
198  }
199  }
200 
201 
202  // =====================================================================
203  // =====================================================================
204 
205 
206  /**
207  Resets the option to default (inactive with empty value)
208  */
209  void reset()
210  {
211  m_Active = false;
212  m_Value = "";
213  }
214 
215 };
216 
217 
218 // =====================================================================
219 // =====================================================================
220 
221 
223 {
224  private:
225 
226  std::string m_Name;
227 
228  std::string m_HelpText;
229 
230  std::map<std::string,CommandLineOption> m_Options;
231 
232  std::map<std::string,CommandLineOption*> m_ShortOptions;
233 
234 
235  public:
236 
238  { }
239 
240 
241  // =====================================================================
242  // =====================================================================
243 
244 
245  /**
246  Instanciates a command with the given parameters
247  @param[in] Name The long name of the command
248  @param[in] HelpText The help text associated to the command
249  */
250  CommandLineCommand(const std::string& Name, const std::string& HelpText):
251  m_Name(Name), m_HelpText(HelpText)
252  { }
253 
254 
255  // =====================================================================
256  // =====================================================================
257 
258 
259  /**
260  Returns the help text of the command
261  @return The help text
262  */
263  std::string getHelpText() const
264  {
265  return m_HelpText;
266  }
267 
268 
269  // =====================================================================
270  // =====================================================================
271 
272 
273  /**
274  Returns the name of the command
275  @return The name (e.g. "search")
276  */
277  std::string getName() const
278  {
279  return m_Name;
280  }
281 
282 
283  // =====================================================================
284  // =====================================================================
285 
286 
287  /**
288  Returns the options registered for the command
289  @return The options
290  */
291  const std::map<std::string,CommandLineOption>& options()
292  {
293  return m_Options;
294  }
295 
296 
297  // =====================================================================
298  // =====================================================================
299 
300 
301  /**
302  Adds an option to the command
303  @param[in] Option The option to add
304  */
305  void addOption(const CommandLineOption& Option)
306  {
307  m_Options[Option.getLongName()] = Option;
308 
309  if (!Option.getShortName().empty())
310  {
311  m_ShortOptions[Option.getShortName()] = &m_Options[Option.getLongName()];
312  }
313  }
314 
315 
316  // =====================================================================
317  // =====================================================================
318 
319 
320  /**
321  Activates the given option with the given value
322  @param[in] LongName The long name of the option
323  @param[in] Value The value for activation (default is empty)
324  */
325  bool activateOption(const std::string& LongName, const std::string& Value = "")
326  {
327  auto it = m_Options.find(LongName);
328 
329  if (it == m_Options.end())
330  {
331  return false;
332  }
333 
334  (*it).second.activate(Value);
335  return (*it).second.isActive();
336  }
337 
338 
339  // =====================================================================
340  // =====================================================================
341 
342 
343  /**
344  Returns the long name of an option from its short name
345  @param[in] ShortName The requested short name for the option
346  @return The long name
347  */
348  std::string getOptionNameFromShortName(const std::string& ShortName) const
349  {
350  auto it = m_ShortOptions.find(ShortName);
351 
352  if (it == m_ShortOptions.end())
353  {
354  return "";
355  }
356 
357  return (*it).second->getLongName();
358  }
359 
360 
361  // =====================================================================
362  // =====================================================================
363 
364 
365  /**
366  Tests if an option exists for the command
367  @param[in] LongName The long name for the searched option
368  @return true if the option exists
369  */
370  bool isOptionExists(const std::string& LongName) const
371  {
372  return (m_Options.find(LongName) != m_Options.end());
373  }
374 
375 
376  // =====================================================================
377  // =====================================================================
378 
379 
380  /**
381  Tests if an option requires a value
382  @param[in] LongName The long name for the searched option
383  @return true if the option requires a value
384  */
385  bool isOptionRequiresValue(const std::string& LongName) const
386  {
387  auto it = m_Options.find(LongName);
388 
389  if (it == m_Options.end())
390  {
391  return false;
392  }
393 
394  return (*it).second.isValueRequired();
395  }
396 
397 
398  // =====================================================================
399  // =====================================================================
400 
401 
402  /**
403  Tests if an option is active
404  @param[in] LongName The long name for the searched option
405  @return true if the option is active
406  */
407  bool isOptionActive(const std::string& LongName) const
408  {
409  auto it = m_Options.find(LongName);
410 
411  return (it != m_Options.end() && (*it).second.isActive());
412  }
413 
414 
415  // =====================================================================
416  // =====================================================================
417 
418 
419  /**
420  Returns the value given for an option
421  @param[in] LongName The long name for the option
422  @return the value for the option
423  */
424  std::string getOptionValue(const std::string& LongName) const
425  {
426  auto it = m_Options.find(LongName);
427 
428  if (it == m_Options.end())
429  {
430  return "";
431  }
432 
433  return ((*it).second.getValue());
434  }
435 
436 
437  // =====================================================================
438  // =====================================================================
439 
440 
441  /**
442  Resets all options to default (inactive with empty value)
443  */
444  void reset()
445  {
446  for (auto& Opt : m_Options)
447  {
448  Opt.second.reset();
449  }
450  }
451 
452 };
453 
454 
455 // =====================================================================
456 // =====================================================================
457 
458 
459 // OpenFLUID:stylecheck:!incs
460 
461 /**
462  @brief Class for management of command line arguments.
463 
464  This class allows to manage the command line arguments as commands, options and extra arguments.
465 
466  The example below is for a command line program with two commands ('run' and 'search') and associated options
467 @snippet misc/main.cpp cmdlineparser
468 */
470 {
471  private:
472 
473  std::string m_ProgramName;
474 
475  std::string m_HelpText;
476 
477  std::map<std::string,CommandLineCommand> m_Commands;
478 
479  std::string m_ActiveCommand;
480 
481  std::vector<std::string> m_ExtraArgs;
482 
483  std::string m_ParsingMessage;
484 
485  bool m_HelpAsked;
486 
487 
488  public:
489 
491  m_HelpAsked(false)
492  {
493  addCommand(CommandLineCommand("",""));
494  }
495 
496 
497  // =====================================================================
498  // =====================================================================
499 
500 
501  /**
502  Instanciates a command line parser with the given parameters
503  @param[in] ProgramName The name of the programn
504  @param[in] HelpText The help text associated to the option
505  */
506  CommandLineParser(const std::string& ProgramName, const std::string& HelpText) :
507  m_ProgramName(ProgramName), m_HelpText(HelpText), m_HelpAsked(false)
508  {
509  addCommand(CommandLineCommand("",""));
510  }
511 
512 
513  // =====================================================================
514  // =====================================================================
515 
516 
517  /**
518  Returns the extra arguments given to the command
519  @return a vector of arguments
520  */
521  const std::vector<std::string>& extraArgs() const
522  {
523  return m_ExtraArgs;
524  }
525 
526 
527  // =====================================================================
528  // =====================================================================
529 
530 
531  /**
532  Returns the help text of the parser
533  @return The help text
534  */
535  std::string getHelpText() const
536  {
537  return m_HelpText;
538  }
539 
540 
541  // =====================================================================
542  // =====================================================================
543 
544 
545  /**
546  Returns the program name
547  @return The program name
548  */
549  std::string getProgramName() const
550  {
551  return m_ProgramName;
552  }
553 
554 
555  // =====================================================================
556  // =====================================================================
557 
558 
559  /**
560  Returns the message given by the parsing process in case of error(s)
561  @return The message
562  */
563  std::string getParsingMessage() const
564  {
565  return m_ParsingMessage;
566  }
567 
568 
569  // =====================================================================
570  // =====================================================================
571 
572 
573  /**
574  Returns the active command name
575  @return The active command name
576  */
577  std::string getActiveCommand() const
578  {
579  return m_ActiveCommand;
580  }
581 
582 
583  // =====================================================================
584  // =====================================================================
585 
586 
587  /**
588  Returns the command corresponding to the given name
589  @param[in] Name the name of the command
590  @return The command object
591  */
592  const CommandLineCommand& command(const std::string& Name) const
593  {
594  return m_Commands.at(Name);
595  }
596 
597 
598  // =====================================================================
599  // =====================================================================
600 
601 
602  /**
603  Adds a command to the parser
604  @param[in] Command The command to add
605  */
606  void addCommand(const CommandLineCommand& Command)
607  {
608  m_Commands[Command.getName()] = Command;
609  }
610 
611 
612  // =====================================================================
613  // =====================================================================
614 
615 
616  /**
617  Adds a global option to the parser
618  @param[in] Option The option to add
619  */
620  void addOption(const CommandLineOption& Option)
621  {
622  m_Commands[""].addOption(Option);
623  }
624 
625 
626  // =====================================================================
627  // =====================================================================
628 
629 
630  /**
631  Parses a list of string arguments
632  @param[in] ArgValues The lists of arguments to parse
633  @return true if the parsing is succesful, false otherwise
634  */
635  bool parse(std::list<std::string> ArgValues)
636  {
637  reset();
638 
639  while (!ArgValues.empty())
640  {
641  std::string Arg = ArgValues.front();
642  ArgValues.pop_front();
643 
644  if (Arg[0] != '-')
645  {
646  // arg not an option
647  if (m_ActiveCommand.empty())
648  {
649  m_ActiveCommand = Arg;
650  }
651  else
652  {
653  m_ExtraArgs.push_back(Arg);
654  }
655  }
656  else
657  {
658  // arg is an option
659 
660  // check if the command exists
661  auto it = m_Commands.find(m_ActiveCommand);
662  if (it == m_Commands.end())
663  {
664  m_ParsingMessage = "unknown \""+ m_ActiveCommand + "\" command";
665  return false;
666  }
667 
668  if (Arg == "-h" || Arg == "--help")
669  {
670  m_HelpAsked = true;
671  }
672  else if (Arg.size() < 2)
673  {
674  m_ParsingMessage = "wrong format for option \"" + Arg + "\"";
675  return false;
676  }
677  else
678  {
679  std::string LongOptName;
680  std::string OptValue;
681  bool IsFromShort = false;
682 
683  if (Arg[1] != '-')
684  {
685  if (Arg.size() != 2)
686  {
687  m_ParsingMessage = "wrong format for short option \"" + Arg + "\"";
688  return false;
689  }
690 
691  // short option
692  LongOptName = m_Commands[m_ActiveCommand].getOptionNameFromShortName(Arg.substr(1,1));
693  IsFromShort = true;
694  }
695  else
696  {
697  // long option
698  std::string TmpName = Arg.substr(2,Arg.size()-2);
699 
700  std::string::size_type EqualPos = TmpName.find("=");
701 
702  if (EqualPos != std::string::npos)
703  {
704  LongOptName = TmpName.substr(0,EqualPos);
705  OptValue = TmpName.substr(EqualPos+1,TmpName.size()-EqualPos-1);
706  }
707  else
708  {
709  LongOptName = TmpName;
710  }
711  }
712 
713  if (!m_Commands[m_ActiveCommand].isOptionExists(LongOptName))
714  {
715  // unknown option
716  m_ParsingMessage = "unknown option \"" + Arg + "\"";
717  if (!m_ActiveCommand.empty())
718  {
719  m_ParsingMessage += " for command \"" + m_ActiveCommand + "\"";
720  }
721  return false;
722  }
723 
724  if (m_Commands[m_ActiveCommand].isOptionRequiresValue(LongOptName))
725  {
726  if (IsFromShort && !ArgValues.empty())
727  {
728  OptValue = ArgValues.front();
729  ArgValues.pop_front();
730  }
731 
732  if (OptValue.empty())
733  {
734  m_ParsingMessage = "missing value for option \"" + Arg + "\"";
735  return false;
736  }
737  }
738 
739  if (!m_Commands[m_ActiveCommand].activateOption(LongOptName,OptValue))
740  {
741  // wrong option format
742  m_ParsingMessage = "unknown error for option \"" + Arg + "\"";
743  return false;
744  }
745  }
746  }
747  }
748  return true;
749  }
750 
751 
752  // =====================================================================
753  // =====================================================================
754 
755 
756  /**
757  Parses arguments from the standard parameters `(int argc,char** argv)` given through the main function
758  @param[in] ArgC The number of arguments
759  @param[in] ArgV The array of arguments
760  @return true if the parsing is succesful, false otherwise
761  */
762  bool parse(int ArgC, char **ArgV)
763  {
764  std::list<std::string> ArgValues;
765 
766  for (int i=1; i< ArgC; i++)
767  {
768  ArgValues.push_back(std::string(ArgV[i]));
769  }
770 
771  return parse(ArgValues);
772  }
773 
774 
775  // =====================================================================
776  // =====================================================================
777 
778 
779  /**
780  Resets the parser to default (no active command, no extra arguments, no option activated)
781  */
782  void reset()
783  {
784  m_ActiveCommand.clear();
785  m_ParsingMessage.clear();
786  m_ExtraArgs.clear();
787 
788  for (auto& Cmd : m_Commands)
789  {
790  Cmd.second.reset();
791  }
792  }
793 
794 
795  // =====================================================================
796  // =====================================================================
797 
798 
799  /**
800  Tests if the help is asked
801  @return true if the help is asked
802  */
803  bool isHelpAsked()
804  {
805  return m_HelpAsked;
806  }
807 
808 
809  // =====================================================================
810  // =====================================================================
811 
812 
813  /**
814  Prints the help text
815  @param[in] OutStm The stream where the help text is printed (e.g. std::cout)
816  */
817  void printHelp(std::ostream& OutStm)
818  {
819  std::string m_CmdName = m_ActiveCommand;
820 
821  if (m_CmdName.empty())
822  {
823  m_CmdName = "[<command>]";
824  }
825 
826  OutStm << "Usage : " << m_ProgramName << " " << m_CmdName << " [<options>] [<args>]\n";
827 
828  if (m_ActiveCommand.empty())
829  {
830  OutStm << "\nAvailable commands:\n";
831 
832  for (auto& Cmd : m_Commands)
833  {
834  if (!Cmd.first.empty())
835  {
836  OutStm << " " << Cmd.first << " : " << Cmd.second.getHelpText() << "\n";
837  }
838  }
839  }
840 
841  if (!m_Commands[m_ActiveCommand].getHelpText().empty())
842  {
843  OutStm << "\n" << m_Commands[m_ActiveCommand].getHelpText() << "\n";
844  }
845 
846  OutStm << "\nAvailable options:\n";
847  OutStm << " --help,-h : display this help message\n";
848 
849  for (auto& Opt : m_Commands[m_ActiveCommand].options())
850  {
851  OutStm << " --" << Opt.second.getLongName();
852  if (Opt.second.isValueRequired())
853  {
854  OutStm << "=<arg>";
855  }
856 
857  if (!Opt.second.getShortName().empty())
858  {
859  OutStm << ", -" << Opt.second.getShortName();
860  if (Opt.second.isValueRequired())
861  {
862  OutStm << " <arg>";
863  }
864  }
865 
866  OutStm << " : " << Opt.second.getHelpText() << "\n";
867  }
868  }
869 
870 
871  // =====================================================================
872  // =====================================================================
873 
874 
875  /**
876  Prints the state of the parser
877  @param[in] OutStm The stream where the help text is printed (e.g. std::cout)
878  */
879  void printState(std::ostream& OutStm)
880  {
881  for (auto& Cmd : m_Commands)
882  {
883  if (!Cmd.first.empty())
884  {
885  if (Cmd.first == m_ActiveCommand)
886  {
887  OutStm << "+";
888  }
889  else
890  {
891  OutStm << "-";
892  }
893 
894  OutStm << " " << Cmd.first << " : " << Cmd.second.getHelpText() << "\n";
895 
896  for (auto& Opt : Cmd.second.options())
897  {
898  OutStm << " ";
899 
900  if (Opt.second.isActive())
901  {
902  OutStm << "+";
903  }
904  else
905  {
906  OutStm << "-";
907  }
908  OutStm << " " << Opt.first;
909 
910  if (!Opt.second.getShortName().empty())
911  {
912  OutStm << "," << Opt.second.getShortName();
913  }
914 
915  if (Opt.second.isValueRequired())
916  {
917  OutStm << "[" << Opt.second.getValue() << "]";
918  }
919 
920  OutStm << " : " << Opt.second.getHelpText() << "\n";
921  }
922  }
923  }
924 
925 
926  if (!m_ExtraArgs.empty())
927  {
928  OutStm << "Extra arguments :";
929 
930  for (auto& Arg : m_ExtraArgs)
931  {
932  OutStm << " " << Arg;
933  }
934 
935  OutStm << "\n";
936  }
937 
938  }
939 
940 };
941 
942 
943 } }
944 
945 
946 #endif /* __OPENFLUID_UTILS_COMMANDLINEPARSER_HPP__ */
std::string getActiveCommand() const
Definition: CommandLineParser.hpp:577
const std::vector< std::string > & extraArgs() const
Definition: CommandLineParser.hpp:521
CommandLineCommand(const std::string &Name, const std::string &HelpText)
Definition: CommandLineParser.hpp:250
Definition: ApplicationException.hpp:47
Definition: CommandLineParser.hpp:222
std::string getLongName() const
Definition: CommandLineParser.hpp:117
CommandLineCommand()
Definition: CommandLineParser.hpp:237
CommandLineParser()
Definition: CommandLineParser.hpp:490
void reset()
Definition: CommandLineParser.hpp:444
void activate(const std::string &Value="")
Definition: CommandLineParser.hpp:187
std::string getName() const
Definition: CommandLineParser.hpp:277
void addOption(const CommandLineOption &Option)
Definition: CommandLineParser.hpp:620
bool isValueRequired() const
Definition: CommandLineParser.hpp:173
Definition: CommandLineParser.hpp:53
void reset()
Definition: CommandLineParser.hpp:209
void addCommand(const CommandLineCommand &Command)
Definition: CommandLineParser.hpp:606
bool isOptionActive(const std::string &LongName) const
Definition: CommandLineParser.hpp:407
std::string getOptionValue(const std::string &LongName) const
Definition: CommandLineParser.hpp:424
std::string getShortName() const
Definition: CommandLineParser.hpp:131
bool isHelpAsked()
Definition: CommandLineParser.hpp:803
bool parse(std::list< std::string > ArgValues)
Definition: CommandLineParser.hpp:635
bool parse(int ArgC, char **ArgV)
Definition: CommandLineParser.hpp:762
CommandLineParser(const std::string &ProgramName, const std::string &HelpText)
Definition: CommandLineParser.hpp:506
void addOption(const CommandLineOption &Option)
Definition: CommandLineParser.hpp:305
std::string getHelpText() const
Definition: CommandLineParser.hpp:263
std::string getProgramName() const
Definition: CommandLineParser.hpp:549
bool isOptionExists(const std::string &LongName) const
Definition: CommandLineParser.hpp:370
CommandLineOption(const std::string &LongName, const std::string &ShortName, const std::string &HelpText, bool ValueRequired=false)
Definition: CommandLineParser.hpp:88
void printState(std::ostream &OutStm)
Definition: CommandLineParser.hpp:879
bool activateOption(const std::string &LongName, const std::string &Value="")
Definition: CommandLineParser.hpp:325
void printHelp(std::ostream &OutStm)
Definition: CommandLineParser.hpp:817
std::string getValue() const
Definition: CommandLineParser.hpp:145
const CommandLineCommand & command(const std::string &Name) const
Definition: CommandLineParser.hpp:592
bool isOptionRequiresValue(const std::string &LongName) const
Definition: CommandLineParser.hpp:385
bool isActive() const
Definition: CommandLineParser.hpp:159
std::string getHelpText() const
Definition: CommandLineParser.hpp:535
const std::map< std::string, CommandLineOption > & options()
Definition: CommandLineParser.hpp:291
Class for management of command line arguments.
Definition: CommandLineParser.hpp:469
std::string getHelpText() const
Definition: CommandLineParser.hpp:103
std::string getOptionNameFromShortName(const std::string &ShortName) const
Definition: CommandLineParser.hpp:348
CommandLineOption()
Definition: CommandLineParser.hpp:72
void reset()
Definition: CommandLineParser.hpp:782
std::string getParsingMessage() const
Definition: CommandLineParser.hpp:563