Skip to content
Snippets Groups Projects
otbCommandLineArgumentParser.cxx 12.2 KiB
Newer Older
/*
 * 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;