ARGoS  3
A parallel, multi-engine simulator for swarm robotics
core/utility/configuration/command_line_arg_parser.cpp
Go to the documentation of this file.
00001 
00007 #include "command_line_arg_parser.h"
00008 #include <cstring>
00009 
00010 namespace argos {
00011 
00012    /****************************************/
00013    /****************************************/
00014 
00015    CCommandLineArgParser::CCommandLineArgParser() :
00016       m_nCurrentArgument(0) {
00017    }
00018 
00019    /****************************************/
00020    /****************************************/
00021 
00022    CCommandLineArgParser::~CCommandLineArgParser() {
00023       while(! m_vecArguments.empty()) {
00024          delete m_vecArguments.back();
00025          m_vecArguments.pop_back();
00026       }
00027    }
00028 
00029    /****************************************/
00030    /****************************************/
00031 
00032    void CCommandLineArgParser::PrintUsage(CARGoSLog& c_log) {
00033       for(size_t i = 0; i < m_vecArguments.size(); ++i) {
00034          c_log << "-" << m_vecArguments[i]->ShortOption << "|"
00035                << "--" << m_vecArguments[i]->LongOption;
00036          if(!m_vecArguments[i]->IsFlag) {
00037             c_log << " <value>";
00038          }
00039          c_log << "\t"
00040                << m_vecArguments[i]->Description
00041                << std::endl;
00042       }
00043    }
00044 
00045    /****************************************/
00046    /****************************************/
00047 
00048    void CCommandLineArgParser::Parse(SInt32 n_argc,
00049                                      char** ppch_argv) {
00050       /* Used to store information about each argument to parse */
00051       size_t unArgLength;
00052       char* pchCurrentArg;
00053       /* Start parsing from the beginning */
00054       m_nCurrentArgument = 1;
00055       /* Go through all the passed arguments */
00056       while(m_nCurrentArgument < n_argc) {
00057          /*
00058           * Parsing does as follows:
00059           * If the first characters is a - followed by other charactares, then it's an option
00060           *   If the second character is a - too, it's a long one
00061           *   Otherwise it's a (set of) short option(s)
00062           * If the first character is not a -, or the string is just "-", error
00063           */
00064          pchCurrentArg = ppch_argv[m_nCurrentArgument];
00065          unArgLength = ::strlen(pchCurrentArg);
00066          if(ppch_argv[m_nCurrentArgument][0] != '-' ||
00067             unArgLength == 1) {
00068             THROW_ARGOSEXCEPTION("Unrecognized option \"" << pchCurrentArg << "\".");
00069          }
00070          else {
00071             /* The first character is a - and more characters are to come */
00072             if(pchCurrentArg[1] == '-') {
00073                /* Also the second char is a - */
00074                if(unArgLength > 2) {
00075                   /* We have a long option */
00076                   ParseLongOption(n_argc, ppch_argv);
00077                }
00078                else {
00079                   /* It's just a --, which we don't support */
00080                   THROW_ARGOSEXCEPTION("Unrecognized option \"" << pchCurrentArg << "\".");
00081                }
00082             }
00083             else {
00084                /* We have a short option like -x, or a set of them like -xyz */
00085                if(unArgLength == 2) {
00086                   /* Single short option: -x */
00087                   ParseShortOption(n_argc, ppch_argv);
00088                }
00089                else {
00090                   /* Set of short options: -xyz */
00091                   ParseShortOptions(n_argc, ppch_argv);
00092                }
00093             }
00094          }
00095          /* Parse next option */
00096          ++m_nCurrentArgument;
00097       }
00098    }
00099 
00100    /****************************************/
00101    /****************************************/
00102 
00103    void CCommandLineArgParser::ParseLongOption(SInt32 n_argc,
00104                                                char** ppch_argv) {
00105       /* Strip the initial -- from the option */
00106       std::string strArg(ppch_argv[m_nCurrentArgument]+2);
00107       try {
00108          /* Search for the option in the vector */
00109          for(size_t i = 0; i < m_vecArguments.size(); ++i) {
00110             if(m_vecArguments[i]->LongOption == strArg) {
00111                /* The option has been found */
00112                if(m_vecArguments[i]->IsFlag) {
00113                   /* It's a flag, pass "true" to set the boolean to true */
00114                   m_vecArguments[i]->Parse("true");
00115                }
00116                else {
00117                   /* It's an argument, use what follows as parameter */
00118                   ++m_nCurrentArgument;
00119                   if(m_nCurrentArgument == n_argc) {
00120                      THROW_ARGOSEXCEPTION("Missing argument for option \"--" << strArg << "\".");
00121                   }
00122                   m_vecArguments[i]->Parse(ppch_argv[m_nCurrentArgument]);
00123                }
00124                /* No need to continue searching */
00125                return;
00126             }
00127          }
00128       }
00129       catch(CARGoSException& ex) {
00130          /* Something went wrong with the parsing */
00131          THROW_ARGOSEXCEPTION_NESTED("Error parsing option \"--" << strArg << "\".", ex);
00132       }
00133       /* If you get here, it's because the option hasn't been found */
00134       THROW_ARGOSEXCEPTION("Unrecognized option \"--" << strArg << "\".");
00135    }
00136 
00137    /****************************************/
00138    /****************************************/
00139 
00140    void CCommandLineArgParser::ParseShortOption(SInt32 n_argc,
00141                                                 char** ppch_argv) {
00142       /* Strip the initial - from the option */
00143       char strArg(ppch_argv[m_nCurrentArgument][1]);
00144       try {
00145          /* Search for the option in the vector */
00146          for(size_t i = 0; i < m_vecArguments.size(); ++i) {
00147             if(m_vecArguments[i]->ShortOption == strArg) {
00148                /* The option has been found */
00149                if(m_vecArguments[i]->IsFlag) {
00150                   /* It's a flag, pass "true" to set the boolean to true */
00151                   m_vecArguments[i]->Parse("true");
00152                }
00153                else {
00154                   /* It's an argument, use what follows as parameter */
00155                   ++m_nCurrentArgument;
00156                   if(m_nCurrentArgument == n_argc) {
00157                      THROW_ARGOSEXCEPTION("Missing argument for option \"-" << strArg << "\".");
00158                   }
00159                   m_vecArguments[i]->Parse(ppch_argv[m_nCurrentArgument]);
00160                }
00161                /* No need to continue searching */
00162                return;
00163             }
00164          }
00165       }
00166       catch(CARGoSException& ex) {
00167          /* Something went wrong with the parsing */
00168          THROW_ARGOSEXCEPTION_NESTED("Error parsing option \"-" << strArg << "\".", ex);
00169       }
00170       /* If you get here, it's because the option hasn't been found */
00171       THROW_ARGOSEXCEPTION("Unrecognized option \"-" << strArg << "\".");
00172    }
00173 
00174    /****************************************/
00175    /****************************************/
00176 
00177    void CCommandLineArgParser::ParseShortOptions(SInt32 n_argc,
00178                                                  char** ppch_argv) {
00179       /* Strip the initial - from the option */
00180       std::string strArg(ppch_argv[m_nCurrentArgument]+1);
00181       /* Go through all options */
00182       for(size_t o = 0; o < strArg.length(); ++o) {
00183          /* Search for the option in the vector */
00184          size_t i = 0;
00185          bool bFound = false;
00186          try {
00187             while(i < m_vecArguments.size() && !bFound) {
00188                if(m_vecArguments[i]->ShortOption == strArg[o]) {
00189                   /* The option has been found */
00190                   if(m_vecArguments[i]->IsFlag) {
00191                      /* It's a flag, pass "true" to set the boolean to true */
00192                      m_vecArguments[i]->Parse("true");
00193                   }
00194                   else {
00195                      /* It's an argument, only the last short option is allowed to have one */
00196                      if(o < strArg.length()-1) {
00197                         THROW_ARGOSEXCEPTION("Option \"-" << strArg[o] << "\" requires an argument.");
00198                      }
00199                      else {
00200                         ++m_nCurrentArgument;
00201                         m_vecArguments[i]->Parse(ppch_argv[m_nCurrentArgument]);
00202                      }
00203                   }
00204                   /* No need to continue searching */
00205                   bFound = true;
00206                }
00207                else {
00208                   /* Try next option */
00209                   ++i;
00210                }
00211             }
00212          }
00213          catch(CARGoSException& ex) {
00214             /* Something went wrong with the parsing */
00215             THROW_ARGOSEXCEPTION_NESTED("Error parsing option \"-" << strArg << "\".", ex);
00216          }
00217          if(!bFound) {
00218             /* The option hasn't been found */
00219             THROW_ARGOSEXCEPTION("Unrecognized option \"-" << strArg[o] << "\".");
00220          }
00221       }
00222    }
00223 
00224    /****************************************/
00225    /****************************************/
00226    
00227 }