Skip to content
Snippets Groups Projects
otbCommandLineArgumentParser.cxx 12.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
     *
     * This file is part of Orfeo Toolbox
     *
     *     https://www.orfeo-toolbox.org/
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    Patrick Imbo's avatar
    Patrick Imbo committed
    
    
    #include "otbCommandLineArgumentParser.h"
    
    #include <assert.h>
    #include <iostream>
    
    Emmanuel Christophe's avatar
    Emmanuel Christophe committed
    
    #include "itkMacro.h"
    
    Emmanuel Christophe's avatar
    Emmanuel Christophe committed
    #include "otbConfigure.h" // For OTB_VERSION_STRING generated by ccmake
    
    Emmanuel Christophe's avatar
    Emmanuel Christophe committed
    // --------- CommandLineArgumentParseResult
    // --------- ----------------------------------------
    CommandLineArgumentParseResult::CommandLineArgumentParseResult() {}
    
    CommandLineArgumentParseResult::~CommandLineArgumentParseResult() {}
    
    
    void CommandLineArgumentParseResult
    
    ::PrintSelf(std::ostream& itkNotUsed(os), itk::Indent itkNotUsed(indent)) const
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
    
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
    
    
    bool CommandLineArgumentParseResult
    
    ::IsOptionPresent(const std::string& option) const
    
    {
      return (m_OptionMap.find(option) != m_OptionMap.end());
    }
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
    
    
    bool CommandLineArgumentParseResult
    
    OTB Bot's avatar
    OTB Bot committed
    ::IsOptionInputImagePresent(void) const
    
    {
      return (this->IsOptionPresent("--InputImage"));
    }
    bool CommandLineArgumentParseResult
    
    OTB Bot's avatar
    OTB Bot committed
    ::IsOptionOutputImagePresent(void) const
    
    {
      return (this->IsOptionPresent("--OutputImage"));
    }
    
    bool CommandLineArgumentParseResult
    
    OTB Bot's avatar
    OTB Bot committed
    ::IsOptionOTBTestingPresent(void) const
    
    {
      return (this->IsOptionPresent("--OTBTesting"));
    }
    
    std::string CommandLineArgumentParseResult
    
    ::GetParameterString(const std::string& option, unsigned int number) const
    
    OTB Bot's avatar
    OTB Bot committed
      if (this->IsOptionPresent(option) == false)
        {
    
        std::ostringstream msg;
    
    OTB Bot's avatar
    OTB Bot committed
        msg << "GetParameterString(): The following '" << option << "' option is unknown !!";
    
        CommandLineArgumentParserArgumentErrorException e(__FILE__, __LINE__);
        e.SetDescription(msg.str().c_str());
        throw e;
    
    OTB Bot's avatar
    OTB Bot committed
        }
    
      OptionMapType::const_iterator it = m_OptionMap.begin();
      it = m_OptionMap.find(option);
      ParameterArrayType pat = (*it).second;
    
    OTB Bot's avatar
    OTB Bot committed
      std::string        lString = pat[number];
      return (lString);
    
    std::string CommandLineArgumentParseResult
    ::GetInputImage(void) const
    {
      return (GetParameterString("--InputImage"));
    }
    
    std::string CommandLineArgumentParseResult
    ::GetOutputImage(void) const
    {
      return (GetParameterString("--OutputImage"));
    }
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
    
    
    int CommandLineArgumentParseResult
    
    ::GetNumberOfParameters(const std::string& option)
    
    {
      assert(IsOptionPresent(option));
      return (m_OptionMap[option].size());
    }
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
    
    
    void CommandLineArgumentParseResult
    ::Clear()
    {
      m_OptionMap.clear();
    }
    
    void CommandLineArgumentParseResult
    
    OTB Bot's avatar
    OTB Bot committed
    ::AddOption(const std::string& option)
    
    {
      ParameterArrayType pat;
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
    //  pat.reserve(nParms);
    
      m_OptionMap[option] = pat;
    }
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
    
    
    void CommandLineArgumentParseResult
    
    OTB Bot's avatar
    OTB Bot committed
    ::AddParameter(const std::string& option, const std::string& parameter)
    
    {
      m_OptionMap[option].push_back(parameter);
    }
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
    
    // --------- CommandLineArgumentParser  ----------------------------------------
    
    CommandLineArgumentParser
    ::CommandLineArgumentParser()
    {
    
    OTB Bot's avatar
    OTB Bot committed
      AddOption("--help", "Help", "-h", 0, false);
      AddOption("--version", "Version", "-v", 0, false);
      AddOptionNParams("--OTBTesting", "Testing purposes only.", "-OTBTesting", false);
    
      m_ProgramDescription.clear();
    }
    
    Emmanuel Christophe's avatar
    Emmanuel Christophe committed
    CommandLineArgumentParser
    ::~CommandLineArgumentParser() {}
    
    
    
    void CommandLineArgumentParser
    ::AddInputImage(bool obligatory)
    {
    
    OTB Bot's avatar
    OTB Bot committed
      AddOption("--InputImage", "input image file name ", "-in", 1, obligatory);
    
    void CommandLineArgumentParser
    ::AddOutputImage(bool obligatory)
    {
    
    OTB Bot's avatar
    OTB Bot committed
      AddOption("--OutputImage", "output image file name ", "-out", 1, obligatory);
    
    void CommandLineArgumentParser
    
    ::AddOption(const std::string& name, const std::string& comment, const std::string& synonym, int nParameters, bool obligatory)
    
      OptionType option;
      option.CommonName  = name;
      option.Description = comment;
    
    Emmanuel Christophe's avatar
    Emmanuel Christophe committed
      option.Synonym     = synonym;
    
      option.NumberOfParameters = nParameters;
      option.NumberOfParametersFixed = true;
      option.Obligatory = obligatory;
      option.Finded = false;
    
      m_OptionList.push_back(option);
    
    void CommandLineArgumentParser
    
    ::AddOptionNParams(const std::string& name, const std::string& comment, const std::string& synonym, bool obligatory)
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
      // Create a structure for the command
    
      OptionType option;
      option.CommonName  = name;
      option.Description = comment;
    
    Emmanuel Christophe's avatar
    Emmanuel Christophe committed
      option.Synonym     = synonym;
    
      option.NumberOfParameters = -1;
      option.NumberOfParametersFixed = false;
      option.Obligatory = obligatory;
      option.Finded = false;
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
      // Add the option to the map
    
      m_OptionList.push_back(option);
    
    void CommandLineArgumentParser
    
    ::ParseCommandLine(int argc, char *argv[],
    
                       CommandLineArgumentParseResult * outResult,
    
    OTB Bot's avatar
    OTB Bot committed
                       bool failOnUnknownTrailingParameters)
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
    {
    
      bool tryParse = TryParseCommandLine(argc, argv, outResult, false, failOnUnknownTrailingParameters);
    
      bool IsHelp = outResult->IsOptionPresent("--help");
    
      if (IsHelp)
    
    OTB Bot's avatar
    OTB Bot committed
        {
    
        PrintUsage(std::cout);
        CommandLineArgumentParserHelpException e(__FILE__, __LINE__);
        e.SetDescription("ParseCommandLine(): Help Parser");
        throw e;
    
    OTB Bot's avatar
    OTB Bot committed
        }
    
      bool IsVersion = outResult->IsOptionPresent("--version");
    
      if (IsVersion)
    
    OTB Bot's avatar
    OTB Bot committed
        {
    
        PrintVersion(std::cout);
        CommandLineArgumentParserHelpException e(__FILE__, __LINE__);
        e.SetDescription("ParseCommandLine(): Version Parser");
        throw e;
    
    OTB Bot's avatar
    OTB Bot committed
        }
    
      tryParse = TryParseCommandLine(argc, argv, outResult, true, failOnUnknownTrailingParameters);
    
      if (!tryParse)
    
    OTB Bot's avatar
    OTB Bot committed
        {
    
        PrintUsage(std::cerr);
        CommandLineArgumentParserArgumentErrorException e(__FILE__, __LINE__);
        e.SetDescription("ParseCommandLine() argument Error");
        throw e;
    
    OTB Bot's avatar
    OTB Bot committed
        }
    
    bool CommandLineArgumentParser::TryParseCommandLine(int argc, char *argv[],
    
    OTB Bot's avatar
    OTB Bot committed
                                                        CommandLineArgumentParseResult * outResult,
                                                        bool reportFailedMsg,
                                                        bool failOnUnknownTrailingParameters)
    
    // Clear the result
    
    Patrick Imbo's avatar
    Patrick Imbo committed
      outResult->Clear();
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
      int index(0);
    
    
    // Go through the arguments
    
    OTB Bot's avatar
    OTB Bot committed
      for (i = 1; i < argc; ++i)
        {
    
    // Get the next argument
    
        std::string arg(argv[i]);
    
        // Check if the argument is known
    
    OTB Bot's avatar
    OTB Bot committed
        bool findOption = FindOption(arg, index);
    
        if (findOption == false)
          {
    
    OTB Bot's avatar
    OTB Bot committed
          if (failOnUnknownTrailingParameters)
    
    OTB Bot's avatar
    OTB Bot committed
            // Unknown argument found
            if (reportFailedMsg == true)
              {
    
              std::cerr << "The following '" << arg << "' option is unknown !!" << std::endl;
    
    OTB Bot's avatar
    OTB Bot committed
              }
    
    OTB Bot's avatar
    OTB Bot committed
            }
    
          else return true;
    
    OTB Bot's avatar
    OTB Bot committed
          }
    
        //Check the option
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
        m_OptionList[index].Finded = true;
    
        // If the number of parameters is predefined
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
        if (m_OptionList[index].NumberOfParametersFixed == true)
    
    OTB Bot's avatar
    OTB Bot committed
          {
    
          // Check if the number of parameters is correct
          int nParameters = m_OptionList[index].NumberOfParameters;
    
    OTB Bot's avatar
    OTB Bot committed
          if (i + nParameters >= argc)
    
    Thomas Feuvrier's avatar
    Thomas Feuvrier committed
            {
    
    OTB Bot's avatar
    OTB Bot committed
            // Too few parameters
            if (reportFailedMsg == true)
              {
    
              std::cerr << "Missing one (or more) parameter(s) for the following '" << arg << "' option." << std::endl;
    
    OTB Bot's avatar
    OTB Bot committed
              }
    
            return false;
    
    OTB Bot's avatar
    OTB Bot committed
            }
    
          // Tell the result that the option has been encountered
    
          outResult->AddOption(m_OptionList[index].CommonName);
    
          // Pass in the parameters
    
    OTB Bot's avatar
    OTB Bot committed
          for (int j = 0; j < nParameters; ++j, ++i)
            {
            outResult->AddParameter(m_OptionList[index].CommonName, std::string(argv[i + 1]));
            }
    
          }
    // If the number of parameters is not defined, read until the next option or the end of argv
        else
    
    OTB Bot's avatar
    OTB Bot committed
          {
    
    // Tell the result that the option has been encountered
          outResult->AddOption(m_OptionList[index].CommonName);
          bool goOnFlag(true);
    
    OTB Bot's avatar
    OTB Bot committed
          while (goOnFlag == true)
    
            if (argv[i + 1] != nullptr)
    
    OTB Bot's avatar
    OTB Bot committed
              std::string strArgv = std::string(argv[i + 1]);
    
              if (strArgv[0] == '-' )
    
    OTB Bot's avatar
    OTB Bot committed
                {
    
                // Test if the string is an argument or a real
                if(!this->IsNumber(strArgv))
                  {
                  goOnFlag = false;
                  }
                else // If not an argument add it to the option list
                  {
                  outResult->AddParameter(m_OptionList[index].CommonName, strArgv);
                  ++i;
                  }
    
    OTB Bot's avatar
    OTB Bot committed
                }
    
              else
    
    OTB Bot's avatar
    OTB Bot committed
                {
                outResult->AddParameter(m_OptionList[index].CommonName, strArgv);
    
    OTB Bot's avatar
    OTB Bot committed
                }
    
              }
            else goOnFlag = false;
    
    OTB Bot's avatar
    OTB Bot committed
            }
    
    OTB Bot's avatar
    OTB Bot committed
        }
    
    // Check that all required arguments are specified
    
      for (unsigned int cpt = 0; cpt < m_OptionList.size(); ++cpt)
    
    OTB Bot's avatar
    OTB Bot committed
        if ((m_OptionList[cpt].Obligatory == true) && (m_OptionList[cpt].Finded == false))
    
    OTB Bot's avatar
    OTB Bot committed
          // Too few parameters
          if (reportFailedMsg == true)
            {
    
            std::cerr << "'" << m_OptionList[cpt].CommonName << "' argument is required !!!" << std::endl;
    
    OTB Bot's avatar
    OTB Bot committed
            }
    
          return false;
    
    OTB Bot's avatar
    OTB Bot committed
          }
    
    
    // Everything is correct
    
    bool CommandLineArgumentParser::IsNumber(const std::string& text)
    
    OTB Bot's avatar
    OTB Bot committed
      if(text.empty())
    
      // Don't test the sign (-)
      unsigned int i = 1;
      while (text[i])
        {
        if( text[i] != '.' && text[i] != ',')
          {
          if(!isdigit(text[i]))
            {
            return false;
            }
          }
    
    OTB Bot's avatar
    OTB Bot committed
    bool CommandLineArgumentParser::FindOption(const std::string& option, int& index)
    
      //Look through the option list
    
    OTB Bot's avatar
    OTB Bot committed
      bool         optionFoundFlag(false);
      bool         goOnFlag(true);
    
      unsigned int cpt(0);
    
    OTB Bot's avatar
    OTB Bot committed
      std::string  strOption(option);
      while (goOnFlag == true)
    
    Emmanuel Christophe's avatar
    Emmanuel Christophe committed
        if ((m_OptionList[cpt].CommonName == strOption) || (m_OptionList[cpt].Synonym == strOption))
    
    OTB Bot's avatar
    OTB Bot committed
          {
    
          index = cpt;
          goOnFlag = false;
    
          optionFoundFlag = true;
    
    OTB Bot's avatar
    OTB Bot committed
          }
    
    OTB Bot's avatar
    OTB Bot committed
        if (cpt >= m_OptionList.size())
          {
    
          goOnFlag = false;
    
    OTB Bot's avatar
    OTB Bot committed
          }
    
        }
      return (optionFoundFlag);
    
    OTB Bot's avatar
    OTB Bot committed
    void CommandLineArgumentParser::PrintUsage(std::ostream& os) const
    
      os << std::endl;
    
      if (!m_ProgramDescription.empty())
    
    OTB Bot's avatar
    OTB Bot committed
        {
    
        os << m_ProgramDescription << std::endl << std::endl;
    
    OTB Bot's avatar
    OTB Bot committed
        }
    
    OTB Bot's avatar
    OTB Bot committed
      os << " Usage : " << m_ProgramName << std::endl;
    
      // Compute the max width for option display
    
    OTB Bot's avatar
    OTB Bot committed
      int          largeurmax(-1);
    
      unsigned int i;
    
    
    OTB Bot's avatar
    OTB Bot committed
      for (i = 0; i < m_OptionList.size(); ++i)
        {
    
    Emmanuel Christophe's avatar
    Emmanuel Christophe committed
        int largeur = m_OptionList[i].CommonName.size() + m_OptionList[i].Synonym.size();
    
    OTB Bot's avatar
    OTB Bot committed
        if (largeur > largeurmax) largeurmax = largeur;
        }
    
    
      // Check that all required arguments are present on the command line
    
    OTB Bot's avatar
    OTB Bot committed
      for (i = 0; i < m_OptionList.size(); ++i)
    
    OTB Bot's avatar
    OTB Bot committed
        if (m_OptionList[i].CommonName != "--OTBTesting")
          {
    
    Emmanuel Christophe's avatar
    Emmanuel Christophe committed
          int largeur = m_OptionList[i].CommonName.size() + m_OptionList[i].Synonym.size();
    
          os << "      ";
    
    OTB Bot's avatar
    OTB Bot committed
          if (m_OptionList[i].Obligatory == false) os << "[";
    
          else os << " ";
    
    Emmanuel Christophe's avatar
    Emmanuel Christophe committed
          os << m_OptionList[i].CommonName;
    
    Emmanuel Christophe's avatar
    Emmanuel Christophe committed
          if (m_OptionList[i].Synonym.empty() == false)
    
    OTB Bot's avatar
    OTB Bot committed
            {
    
    Emmanuel Christophe's avatar
    Emmanuel Christophe committed
            os << "|" << m_OptionList[i].Synonym;
    
    OTB Bot's avatar
    OTB Bot committed
            }
          if (m_OptionList[i].Obligatory == false) os << "]";
    
          else os << " ";
    //Align the text
    
    OTB Bot's avatar
    OTB Bot committed
          for (int b = largeur; b < largeurmax; b++)
            os << " ";
          os <<   "  :  " << m_OptionList[i].Description;
          if (m_OptionList[i].NumberOfParametersFixed == true)
    
    OTB Bot's avatar
    OTB Bot committed
            switch (m_OptionList[i].NumberOfParameters)
              {
    
    OTB Bot's avatar
    OTB Bot committed
              case 0:
                break;
              case 1:
                os << "  (" << m_OptionList[i].NumberOfParameters << " parameter)";
                break;
              default:
                os << "  (" << m_OptionList[i].NumberOfParameters << " parameters)";
                break;
    
    OTB Bot's avatar
    OTB Bot committed
              }
    
          else
    
    OTB Bot's avatar
    OTB Bot committed
            {
    
            os << "  (N parameters)";
    
    OTB Bot's avatar
    OTB Bot committed
            }
    
          os << std::endl;
    
    OTB Bot's avatar
    OTB Bot committed
          }
    
        }
      os << std::endl;
    
    OTB Bot's avatar
    OTB Bot committed
    void CommandLineArgumentParser::PrintVersion(std::ostream& os) const
    
    OTB Bot's avatar
    OTB Bot committed
      os << " OTB Version : " << OTB_VERSION_STRING << std::endl;