mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Added cvf::ProgramOptions class to Fwk
Integrated from CS PF as of changelist 235
This commit is contained in:
parent
a9140ca894
commit
58412c010c
@ -41,6 +41,7 @@ cvfMutex.h
|
||||
cvfObject.h
|
||||
cvfObject.inl
|
||||
cvfPlane.h
|
||||
cvfProgramOptions.h
|
||||
cvfPropertySet.h
|
||||
cvfPropertySetCollection.h
|
||||
cvfQuat.h
|
||||
@ -80,6 +81,7 @@ cvfMath.cpp
|
||||
cvfMutex.cpp
|
||||
cvfObject.cpp
|
||||
cvfPlane.cpp
|
||||
cvfProgramOptions.cpp
|
||||
cvfPropertySet.cpp
|
||||
cvfPropertySetCollection.cpp
|
||||
cvfString.cpp
|
||||
|
@ -254,6 +254,7 @@
|
||||
<ClInclude Include="cvfMutex.h" />
|
||||
<ClInclude Include="cvfObject.h" />
|
||||
<ClInclude Include="cvfPlane.h" />
|
||||
<ClInclude Include="cvfProgramOptions.h" />
|
||||
<ClInclude Include="cvfPropertySet.h" />
|
||||
<ClInclude Include="cvfPropertySetCollection.h" />
|
||||
<ClInclude Include="cvfQuat.h" />
|
||||
@ -302,6 +303,7 @@
|
||||
<ClCompile Include="cvfMutex.cpp" />
|
||||
<ClCompile Include="cvfObject.cpp" />
|
||||
<ClCompile Include="cvfPlane.cpp" />
|
||||
<ClCompile Include="cvfProgramOptions.cpp" />
|
||||
<ClCompile Include="cvfPropertySet.cpp" />
|
||||
<ClCompile Include="cvfPropertySetCollection.cpp" />
|
||||
<ClCompile Include="cvfString.cpp" />
|
||||
|
@ -42,6 +42,7 @@
|
||||
<ClInclude Include="cvfLogDestination.h" />
|
||||
<ClInclude Include="cvfLogDestinationConsole.h" />
|
||||
<ClInclude Include="cvfLogDestinationFile.h" />
|
||||
<ClInclude Include="cvfProgramOptions.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cvfArray.inl" />
|
||||
@ -86,5 +87,6 @@
|
||||
<ClCompile Include="cvfLogManager.cpp" />
|
||||
<ClCompile Include="cvfLogDestinationConsole.cpp" />
|
||||
<ClCompile Include="cvfLogDestinationFile.cpp" />
|
||||
<ClCompile Include="cvfProgramOptions.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
603
Fwk/VizFwk/LibCore/cvfProgramOptions.cpp
Normal file
603
Fwk/VizFwk/LibCore/cvfProgramOptions.cpp
Normal file
@ -0,0 +1,603 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2013 Ceetron AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfProgramOptions.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class ProgramOptions::OptionSpec : public Object
|
||||
{
|
||||
public:
|
||||
OptionSpec(const String& name, const String& valueSyntax, const String& descr, ValueReq valReq, OptionFlags optflags)
|
||||
: m_name(name), m_valueSyntax(valueSyntax), m_descr(descr), m_valueReq(valReq), m_optionFlags(optflags)
|
||||
{}
|
||||
|
||||
public:
|
||||
const String m_name;
|
||||
const String m_valueSyntax;
|
||||
const String m_descr;
|
||||
const ValueReq m_valueReq;
|
||||
const OptionFlags m_optionFlags;
|
||||
};
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class ProgramOptions::ParsedOption : public Object
|
||||
{
|
||||
public:
|
||||
ParsedOption(const OptionSpec* optionSpec)
|
||||
: m_spec(optionSpec)
|
||||
{}
|
||||
|
||||
/// Check if the option has enough actual values compared to the requirements in spec
|
||||
bool hasEnoughValues() const
|
||||
{
|
||||
const size_t numParsedValues = m_values.size();
|
||||
|
||||
CVF_ASSERT(m_spec.notNull());
|
||||
if (m_spec->m_valueReq == NO_VALUE)
|
||||
{
|
||||
CVF_ASSERT(numParsedValues == 0);
|
||||
return true;
|
||||
}
|
||||
else if (m_spec->m_valueReq == SINGLE_VALUE)
|
||||
{
|
||||
CVF_ASSERT(numParsedValues <= 1);
|
||||
return (numParsedValues == 1) ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (numParsedValues >= 1) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we're full
|
||||
bool canAcceptMoreValues() const
|
||||
{
|
||||
const size_t numParsedValues = m_values.size();
|
||||
|
||||
CVF_ASSERT(m_spec.notNull());
|
||||
if (m_spec->m_valueReq == NO_VALUE)
|
||||
{
|
||||
CVF_ASSERT(numParsedValues == 0);
|
||||
return false;
|
||||
}
|
||||
else if (m_spec->m_valueReq == SINGLE_VALUE)
|
||||
{
|
||||
CVF_ASSERT(numParsedValues <= 1);
|
||||
return (numParsedValues == 0) ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
cref<OptionSpec> m_spec;
|
||||
std::vector<String> m_values;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::ProgramOptions
|
||||
/// \ingroup Core
|
||||
///
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ProgramOptions::ProgramOptions()
|
||||
: m_optionPrefix(DOUBLE_DASH)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ProgramOptions::~ProgramOptions()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void ProgramOptions::setOptionPrefix(OptionPrefix prefix)
|
||||
{
|
||||
m_optionPrefix = prefix;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool ProgramOptions::registerOption(const String& optionName, ValueReq valueReq, OptionFlags optionFlags)
|
||||
{
|
||||
return registerOption(optionName, "", "", valueReq, optionFlags);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool ProgramOptions::registerOption(const String& optionName, const String& valueSyntax, const String& description, ValueReq valueReq, OptionFlags optionFlags)
|
||||
{
|
||||
if (optionName.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (findOptionSpec(optionName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ref<OptionSpec> newOpt = new OptionSpec(optionName, valueSyntax, description, valueReq, optionFlags);
|
||||
m_optionSpecs.push_back(newOpt.p());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool ProgramOptions::parse(const std::vector<String>& commandLineArguments)
|
||||
{
|
||||
const String prefixStr = prefixString();
|
||||
const size_t prefixLen = prefixStr.size();
|
||||
|
||||
m_parsedOptions.clear();
|
||||
m_positionalParams.clear();
|
||||
m_unknownOptions.clear();
|
||||
m_optionsWithMissingValues.clear();
|
||||
|
||||
ref<ParsedOption> currParseOption;
|
||||
|
||||
const size_t numCmdLineArgs = commandLineArguments.size();
|
||||
size_t ia = 1;
|
||||
while (ia < numCmdLineArgs)
|
||||
{
|
||||
String arg = commandLineArguments[ia];
|
||||
arg = arg.trimmed();
|
||||
if (arg.isEmpty())
|
||||
{
|
||||
ia++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg.startsWith(prefixStr))
|
||||
{
|
||||
// Finish the option currently being parsed if any
|
||||
if (currParseOption.notNull())
|
||||
{
|
||||
if (currParseOption->hasEnoughValues())
|
||||
{
|
||||
addNewParsedOption(currParseOption.p());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_optionsWithMissingValues.push_back(currParseOption->m_spec->m_name);
|
||||
}
|
||||
|
||||
currParseOption = NULL;
|
||||
}
|
||||
|
||||
if (arg.size() > prefixLen)
|
||||
{
|
||||
const String optName = arg.subString(prefixLen);
|
||||
const OptionSpec* optSpec = findOptionSpec(optName);
|
||||
if (optSpec)
|
||||
{
|
||||
currParseOption = new ParsedOption(optSpec);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_unknownOptions.push_back(optName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine if this arg belongs as a value to the option currently being parsed or if it is a positional parameter
|
||||
if (currParseOption.notNull())
|
||||
{
|
||||
// Simple flags should never get here
|
||||
CVF_ASSERT(currParseOption->m_spec->m_valueReq != NO_VALUE);
|
||||
|
||||
CVF_ASSERT(currParseOption->canAcceptMoreValues());
|
||||
currParseOption->m_values.push_back(arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_positionalParams.push_back(arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (currParseOption.notNull())
|
||||
{
|
||||
if (!currParseOption->canAcceptMoreValues())
|
||||
{
|
||||
addNewParsedOption(currParseOption.p());
|
||||
currParseOption = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ia++;
|
||||
}
|
||||
|
||||
// Finish the option currently being parsed if any
|
||||
if (currParseOption.notNull())
|
||||
{
|
||||
if (currParseOption->hasEnoughValues())
|
||||
{
|
||||
addNewParsedOption(currParseOption.p());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_optionsWithMissingValues.push_back(currParseOption->m_spec->m_name);
|
||||
}
|
||||
|
||||
currParseOption = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (m_unknownOptions.empty() && m_optionsWithMissingValues.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void ProgramOptions::addNewParsedOption(ParsedOption* parsedOption)
|
||||
{
|
||||
const OptionSpec* optSpec = parsedOption->m_spec.p();
|
||||
CVF_ASSERT(optSpec);
|
||||
|
||||
// Check if option already exists
|
||||
ref<ParsedOption> existingOption = findParsedOption(optSpec->m_name);
|
||||
|
||||
|
||||
if (existingOption.notNull())
|
||||
{
|
||||
if (optSpec->m_optionFlags.testFlag(COMBINE_REPEATED))
|
||||
{
|
||||
// Add incoming values to the already existing ones
|
||||
existingOption->m_values.insert(existingOption->m_values.end(), parsedOption->m_values.begin(), parsedOption->m_values.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Last occurence wins
|
||||
// Erase existing and add ourselves at the end
|
||||
m_parsedOptions.erase(existingOption.p());
|
||||
m_parsedOptions.push_back(parsedOption);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// First time we see this option so just add it
|
||||
m_parsedOptions.push_back(parsedOption);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool ProgramOptions::hasOption(const String& optionName) const
|
||||
{
|
||||
if (findParsedOption(optionName))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t ProgramOptions::valueCount(const String& optionName) const
|
||||
{
|
||||
const ParsedOption* parsedOption = findParsedOption(optionName);
|
||||
if (parsedOption)
|
||||
{
|
||||
return parsedOption->m_values.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<String> ProgramOptions::values(const String& optionName) const
|
||||
{
|
||||
const ParsedOption* parsedOption = findParsedOption(optionName);
|
||||
if (parsedOption)
|
||||
{
|
||||
return parsedOption->m_values;
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::vector<String>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
String ProgramOptions::combinedValues(const String& optionName) const
|
||||
{
|
||||
String combined;
|
||||
const ParsedOption* parsedOption = findParsedOption(optionName);
|
||||
if (parsedOption)
|
||||
{
|
||||
for (size_t i = 0; i < parsedOption->m_values.size(); i++)
|
||||
{
|
||||
if (i > 0) combined += " ";
|
||||
combined += parsedOption->m_values[i];
|
||||
}
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<String> ProgramOptions::positionalParameters() const
|
||||
{
|
||||
return m_positionalParams;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<String> ProgramOptions::unknownOptions() const
|
||||
{
|
||||
return m_unknownOptions;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<String> ProgramOptions::optionsWithMissingValues() const
|
||||
{
|
||||
return m_optionsWithMissingValues;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
String ProgramOptions::prefixString() const
|
||||
{
|
||||
switch (m_optionPrefix)
|
||||
{
|
||||
case DOUBLE_DASH: return "--";
|
||||
case SINGLE_DASH: return "-";
|
||||
case SLASH: return "/";
|
||||
default:
|
||||
CVF_FAIL_MSG("Unhandled option prefix type");
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const ProgramOptions::OptionSpec* ProgramOptions::findOptionSpec(const String& optionName) const
|
||||
{
|
||||
const String lcName = optionName.toLower();
|
||||
for (size_t i = 0; i < m_optionSpecs.size(); i++)
|
||||
{
|
||||
if (m_optionSpecs[i]->m_name.toLower() == lcName)
|
||||
{
|
||||
return m_optionSpecs.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const ProgramOptions::ParsedOption* ProgramOptions::findParsedOption(const String& optionName) const
|
||||
{
|
||||
const String lcName = optionName.toLower();
|
||||
for (size_t i = 0; i < m_parsedOptions.size(); i++)
|
||||
{
|
||||
if (m_parsedOptions[i]->m_spec->m_name.toLower() == lcName)
|
||||
{
|
||||
return m_parsedOptions.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ProgramOptions::ParsedOption* ProgramOptions::findParsedOption(const String& optionName)
|
||||
{
|
||||
// Utilize const version
|
||||
return const_cast<ParsedOption*>( (static_cast<const ProgramOptions*>(this))->findParsedOption(optionName) );
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
String ProgramOptions::usageText(int maxWidth, int maxOptionWidth) const
|
||||
{
|
||||
if (maxWidth <= 1) maxWidth = 2;
|
||||
if (maxOptionWidth <= 0) maxOptionWidth = maxWidth/2;
|
||||
|
||||
const String prefixStr = prefixString();
|
||||
|
||||
std::vector<String> optAndValArr;
|
||||
std::vector<String> descrArr;
|
||||
int optAndValMaxLen = 0;
|
||||
|
||||
const size_t numOpts = m_optionSpecs.size();
|
||||
for (size_t i = 0; i < numOpts; i++)
|
||||
{
|
||||
const OptionSpec* spec = m_optionSpecs.at(i);
|
||||
String optAndVal = prefixStr + spec->m_name + String(" ") + spec->m_valueSyntax;
|
||||
optAndValMaxLen = CVF_MAX(optAndValMaxLen, static_cast<int>(optAndVal.size()));
|
||||
|
||||
optAndValArr.push_back(optAndVal);
|
||||
descrArr.push_back(spec->m_descr);
|
||||
}
|
||||
|
||||
|
||||
const int firstColWidth = static_cast<int>(CVF_MIN(optAndValMaxLen + 1, maxOptionWidth));
|
||||
const String firstColBlanks = String("%1").arg("", firstColWidth);
|
||||
|
||||
String retStr;
|
||||
for (size_t iopt = 0; iopt < numOpts; iopt++)
|
||||
{
|
||||
const String optAndVal = optAndValArr[iopt];
|
||||
const String descr = descrArr[iopt];
|
||||
const int optAndValLen = static_cast<int>(optAndVal.size());
|
||||
const int descrLen = static_cast<int>(descr.size());
|
||||
if (optAndValLen + 1 <= firstColWidth &&
|
||||
firstColWidth + descrLen <= maxWidth)
|
||||
{
|
||||
String s = String("%1 %2").arg(optAndValArr[iopt], -(firstColWidth - 1)).arg(descr);
|
||||
retStr += s + String("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
const int maxDescrWidth = CVF_MAX((maxWidth - firstColWidth), 1);
|
||||
std::vector<String> lines = breakStringIntoLines(descr, static_cast<size_t>(maxDescrWidth));
|
||||
|
||||
String s = optAndValArr[iopt];
|
||||
for (size_t i = 0; i < lines.size(); i++)
|
||||
{
|
||||
s += String("\n") + firstColBlanks + lines[i];
|
||||
}
|
||||
retStr += s + String("\n");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return retStr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<String> ProgramOptions::breakStringIntoLines(const String& str, size_t maxCharsPerLine)
|
||||
{
|
||||
std::vector<String> words = str.split();
|
||||
if (words.size() < 1)
|
||||
{
|
||||
return std::vector<String>();
|
||||
}
|
||||
|
||||
std::vector<String> lines;
|
||||
|
||||
String currLine = words[0];
|
||||
const size_t numWords = words.size();
|
||||
for (size_t i = 1; i < numWords; i++)
|
||||
{
|
||||
const String& thisWord = words[i];
|
||||
const size_t thisWordLen = thisWord.size();
|
||||
|
||||
if (currLine.size() + 1 + thisWordLen <= maxCharsPerLine)
|
||||
{
|
||||
currLine += String(" ") + thisWord;
|
||||
}
|
||||
else
|
||||
{
|
||||
lines.push_back(currLine);
|
||||
currLine = thisWord;
|
||||
}
|
||||
}
|
||||
|
||||
lines.push_back(currLine);
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
} // namespace cvf
|
||||
|
120
Fwk/VizFwk/LibCore/cvfProgramOptions.h
Normal file
120
Fwk/VizFwk/LibCore/cvfProgramOptions.h
Normal file
@ -0,0 +1,120 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2013 Ceetron AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfFlags.h"
|
||||
#include "cvfString.h"
|
||||
#include "cvfCollection.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class ProgramOptions
|
||||
{
|
||||
public:
|
||||
enum OptionPrefix
|
||||
{
|
||||
DOUBLE_DASH,
|
||||
SINGLE_DASH,
|
||||
SLASH
|
||||
};
|
||||
|
||||
enum ValueReq
|
||||
{
|
||||
NO_VALUE, // A flag option that does not accept any values
|
||||
SINGLE_VALUE, // Option requires exactly one single value, no more, no less
|
||||
MULTI_VALUE // Option requires one or more values
|
||||
};
|
||||
|
||||
enum OptionFlag
|
||||
{
|
||||
COMBINE_REPEATED = 0x01, // When this flag is specified and an option occurs multiple times, the values will be combined. Default is for the last occurrence to win
|
||||
UNDOCUMENTED = 0x02 // Will not be output in help text
|
||||
};
|
||||
typedef cvf::Flags<OptionFlag> OptionFlags;
|
||||
|
||||
public:
|
||||
ProgramOptions();
|
||||
~ProgramOptions();
|
||||
|
||||
void setOptionPrefix(OptionPrefix prefix);
|
||||
bool registerOption(const String& optionName, ValueReq valueReq = NO_VALUE, OptionFlags optionFlags = OptionFlags());
|
||||
bool registerOption(const String& optionName, const String& valueSyntax, const String& description, ValueReq valueReq = NO_VALUE, OptionFlags optionFlags = OptionFlags());
|
||||
|
||||
bool parse(const std::vector<String>& commandLineArguments);
|
||||
|
||||
bool hasOption(const String& optionName) const;
|
||||
size_t valueCount(const String& optionName) const;
|
||||
std::vector<String> values(const String& optionName) const;
|
||||
String combinedValues(const String& optionName) const;
|
||||
|
||||
std::vector<String> positionalParameters() const;
|
||||
|
||||
std::vector<String> unknownOptions() const;
|
||||
std::vector<String> optionsWithMissingValues() const;
|
||||
|
||||
String usageText(int maxWidth, int maxOptionWidth = -1) const;
|
||||
|
||||
private:
|
||||
class OptionSpec;
|
||||
class ParsedOption;
|
||||
|
||||
String prefixString() const;
|
||||
const OptionSpec* findOptionSpec(const String& optionName) const;
|
||||
const ParsedOption* findParsedOption(const String& optionName) const;
|
||||
ParsedOption* findParsedOption(const String& optionName);
|
||||
void addNewParsedOption(ParsedOption* parsedOption);
|
||||
static std::vector<String> breakStringIntoLines(const String& str, size_t maxCharsPerLine);
|
||||
|
||||
private:
|
||||
OptionPrefix m_optionPrefix; // The prefix to use to identify options
|
||||
Collection<OptionSpec> m_optionSpecs; // Collection of legal registered options
|
||||
Collection<ParsedOption> m_parsedOptions; // The options we have successfully parsed
|
||||
std::vector<String> m_positionalParams; // Array of positional parameters
|
||||
std::vector<String> m_unknownOptions; // Unrecognized options
|
||||
std::vector<String> m_optionsWithMissingValues; // Options that failed during parsing due to missing values
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ cvfMatrix3-Test.cpp
|
||||
cvfMatrix4-Test.cpp
|
||||
cvfObject-Test.cpp
|
||||
cvfPlane-Test.cpp
|
||||
cvfProgramOptions-Test.cpp
|
||||
cvfPropertySet-Test.cpp
|
||||
cvfPropertySetCollection-Test.cpp
|
||||
cvfRect-Test.cpp
|
||||
|
@ -266,6 +266,7 @@
|
||||
<ClCompile Include="cvfMatrix4-Test.cpp" />
|
||||
<ClCompile Include="cvfObject-Test.cpp" />
|
||||
<ClCompile Include="cvfPlane-Test.cpp" />
|
||||
<ClCompile Include="cvfProgramOptions-Test.cpp" />
|
||||
<ClCompile Include="cvfPropertySet-Test.cpp" />
|
||||
<ClCompile Include="cvfPropertySetCollection-Test.cpp" />
|
||||
<ClCompile Include="cvfQuat-Test.cpp" />
|
||||
|
@ -32,6 +32,7 @@
|
||||
<ClCompile Include="cvfLogger-Test.cpp" />
|
||||
<ClCompile Include="cvfLogEvent-Test.cpp" />
|
||||
<ClCompile Include="cvfCodeLocation-Test.cpp" />
|
||||
<ClCompile Include="cvfProgramOptions-Test.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
417
Fwk/VizFwk/Tests/LibCore_UnitTests/cvfProgramOptions-Test.cpp
Normal file
417
Fwk/VizFwk/Tests/LibCore_UnitTests/cvfProgramOptions-Test.cpp
Normal file
@ -0,0 +1,417 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2013 Ceetron AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfProgramOptions.h"
|
||||
#include "cvfTrace.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace cvf;
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, Construction)
|
||||
{
|
||||
ProgramOptions po;
|
||||
ASSERT_FALSE(po.hasOption("dummy"));
|
||||
ASSERT_EQ(0, po.valueCount("dummy"));
|
||||
ASSERT_EQ(0, po.values("dummy").size());
|
||||
ASSERT_TRUE(po.combinedValues("dummy") == "");
|
||||
|
||||
ASSERT_EQ(0, po.positionalParameters().size());
|
||||
ASSERT_EQ(0, po.unknownOptions().size());
|
||||
ASSERT_EQ(0, po.optionsWithMissingValues().size());
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, EmptyOptions)
|
||||
{
|
||||
ProgramOptions po;
|
||||
po.registerOption("flag1");
|
||||
po.registerOption("");
|
||||
|
||||
String cmdLine("MyExe --flag1 -- file1.txt");
|
||||
std::vector<String> cmdLineArgs = cmdLine.split();
|
||||
ASSERT_TRUE(po.parse(cmdLineArgs));
|
||||
|
||||
EXPECT_TRUE(po.hasOption("flag1"));
|
||||
|
||||
ASSERT_EQ(1, po.positionalParameters().size());
|
||||
EXPECT_TRUE(po.positionalParameters()[0] == "file1.txt");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, SimpleFlagOptions)
|
||||
{
|
||||
ProgramOptions po;
|
||||
po.registerOption("flag1");
|
||||
po.registerOption("flag2");
|
||||
po.registerOption("flag3");
|
||||
|
||||
String cmdLine("MyExe --flag3 --flag1");
|
||||
std::vector<String> cmdLineArgs = cmdLine.split();
|
||||
ASSERT_TRUE(po.parse(cmdLineArgs));
|
||||
|
||||
EXPECT_TRUE(po.hasOption("flag1"));
|
||||
EXPECT_TRUE(po.hasOption("flag3"));
|
||||
|
||||
EXPECT_FALSE(po.hasOption("flag2"));
|
||||
EXPECT_FALSE(po.hasOption("flag0"));
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, SingleValueOptions)
|
||||
{
|
||||
ProgramOptions po;
|
||||
po.registerOption("opt1", ProgramOptions::SINGLE_VALUE);
|
||||
po.registerOption("opt2", ProgramOptions::SINGLE_VALUE);
|
||||
po.registerOption("opt3", ProgramOptions::SINGLE_VALUE);
|
||||
|
||||
String cmdLine("MyExe --opt1 AA --opt2 BB");
|
||||
std::vector<String> cmdLineArgs = cmdLine.split();
|
||||
ASSERT_TRUE(po.parse(cmdLineArgs));
|
||||
|
||||
ASSERT_TRUE(po.hasOption("opt1"));
|
||||
ASSERT_EQ(1, po.valueCount("opt1"));
|
||||
EXPECT_TRUE(po.values("opt1")[0] == "AA");
|
||||
|
||||
EXPECT_TRUE(po.hasOption("opt2"));
|
||||
ASSERT_EQ(1, po.valueCount("opt2"));
|
||||
EXPECT_TRUE(po.values("opt2")[0] == "BB");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, MultiValueOptions)
|
||||
{
|
||||
ProgramOptions po;
|
||||
po.registerOption("opt1", ProgramOptions::MULTI_VALUE);
|
||||
po.registerOption("opt2", ProgramOptions::MULTI_VALUE);
|
||||
po.registerOption("opt3", ProgramOptions::MULTI_VALUE);
|
||||
|
||||
String cmdLine("MyExe --opt1 A0 --opt2 B0 B1 --opt3 C0 C1 C2");
|
||||
std::vector<String> cmdLineArgs = cmdLine.split();
|
||||
ASSERT_TRUE(po.parse(cmdLineArgs));
|
||||
|
||||
ASSERT_TRUE(po.hasOption("opt1"));
|
||||
ASSERT_EQ(1, po.valueCount("opt1"));
|
||||
EXPECT_TRUE(po.values("opt1")[0] == "A0");
|
||||
|
||||
EXPECT_TRUE(po.hasOption("opt2"));
|
||||
ASSERT_EQ(2, po.valueCount("opt2"));
|
||||
EXPECT_TRUE(po.values("opt2")[0] == "B0");
|
||||
EXPECT_TRUE(po.values("opt2")[1] == "B1");
|
||||
|
||||
EXPECT_TRUE(po.hasOption("opt3"));
|
||||
ASSERT_EQ(3, po.valueCount("opt3"));
|
||||
EXPECT_TRUE(po.values("opt3")[0] == "C0");
|
||||
EXPECT_TRUE(po.values("opt3")[1] == "C1");
|
||||
EXPECT_TRUE(po.values("opt3")[2] == "C2");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, SingleValueOptionWithMissingValue)
|
||||
{
|
||||
ProgramOptions po;
|
||||
po.registerOption("opt1", ProgramOptions::SINGLE_VALUE);
|
||||
po.registerOption("opt2", ProgramOptions::SINGLE_VALUE);
|
||||
po.registerOption("opt3", ProgramOptions::SINGLE_VALUE);
|
||||
|
||||
String cmdLine("MyExe --opt1 1 --opt2 --opt3 3");
|
||||
std::vector<String> cmdLineArgs = cmdLine.split();
|
||||
ASSERT_FALSE(po.parse(cmdLineArgs));
|
||||
|
||||
ASSERT_TRUE(po.hasOption("opt1"));
|
||||
ASSERT_EQ(1, po.valueCount("opt1"));
|
||||
EXPECT_TRUE(po.values("opt1")[0] == "1");
|
||||
|
||||
EXPECT_FALSE(po.hasOption("opt2"));
|
||||
ASSERT_EQ(0, po.valueCount("opt2"));
|
||||
ASSERT_EQ(1, po.optionsWithMissingValues().size());
|
||||
EXPECT_TRUE(po.optionsWithMissingValues()[0] == "opt2");
|
||||
|
||||
EXPECT_TRUE(po.hasOption("opt3"));
|
||||
ASSERT_EQ(1, po.valueCount("opt3"));
|
||||
EXPECT_TRUE(po.values("opt3")[0] == "3");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, MultiValueOptionWithMissingValues)
|
||||
{
|
||||
ProgramOptions po;
|
||||
po.registerOption("opt1", ProgramOptions::MULTI_VALUE);
|
||||
po.registerOption("opt2", ProgramOptions::MULTI_VALUE);
|
||||
po.registerOption("opt3", ProgramOptions::MULTI_VALUE);
|
||||
|
||||
String cmdLine("MyExe --opt3 1 2 3 --opt2 --opt1 1");
|
||||
std::vector<String> cmdLineArgs = cmdLine.split();
|
||||
ASSERT_FALSE(po.parse(cmdLineArgs));
|
||||
|
||||
ASSERT_TRUE(po.hasOption("opt1"));
|
||||
ASSERT_EQ(1, po.valueCount("opt1"));
|
||||
EXPECT_TRUE(po.values("opt1")[0] == "1");
|
||||
|
||||
EXPECT_FALSE(po.hasOption("opt2"));
|
||||
ASSERT_EQ(0, po.valueCount("opt2"));
|
||||
ASSERT_EQ(1, po.optionsWithMissingValues().size());
|
||||
EXPECT_TRUE(po.optionsWithMissingValues()[0] == "opt2");
|
||||
|
||||
EXPECT_TRUE(po.hasOption("opt3"));
|
||||
ASSERT_EQ(3, po.valueCount("opt3"));
|
||||
EXPECT_TRUE(po.values("opt3")[0] == "1");
|
||||
EXPECT_TRUE(po.values("opt3")[1] == "2");
|
||||
EXPECT_TRUE(po.values("opt3")[2] == "3");
|
||||
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, UnknownOptions)
|
||||
{
|
||||
ProgramOptions po;
|
||||
po.registerOption("noval", ProgramOptions::NO_VALUE);
|
||||
po.registerOption("single", ProgramOptions::SINGLE_VALUE);
|
||||
po.registerOption("multi", ProgramOptions::MULTI_VALUE);
|
||||
|
||||
String cmdLine("MyExe --u1 v1 --multi 1 2 --u2 v2 --noval f1 --u3 --single 1 --u4 f2");
|
||||
std::vector<String> cmdLineArgs = cmdLine.split();
|
||||
ASSERT_FALSE(po.parse(cmdLineArgs));
|
||||
|
||||
ASSERT_TRUE(po.hasOption("noval"));
|
||||
ASSERT_EQ(0, po.valueCount("noval"));
|
||||
ASSERT_TRUE(po.hasOption("single"));
|
||||
ASSERT_EQ(1, po.valueCount("single"));
|
||||
ASSERT_TRUE(po.hasOption("multi"));
|
||||
ASSERT_EQ(2, po.valueCount("multi"));
|
||||
|
||||
ASSERT_EQ(4, po.unknownOptions().size());
|
||||
EXPECT_TRUE(po.unknownOptions()[0] == "u1");
|
||||
EXPECT_TRUE(po.unknownOptions()[1] == "u2");
|
||||
EXPECT_TRUE(po.unknownOptions()[2] == "u3");
|
||||
EXPECT_TRUE(po.unknownOptions()[3] == "u4");
|
||||
|
||||
ASSERT_EQ(4, po.positionalParameters().size());
|
||||
EXPECT_TRUE(po.positionalParameters()[0] == "v1");
|
||||
EXPECT_TRUE(po.positionalParameters()[1] == "v2");
|
||||
EXPECT_TRUE(po.positionalParameters()[2] == "f1");
|
||||
EXPECT_TRUE(po.positionalParameters()[3] == "f2");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, RepeatOptions)
|
||||
{
|
||||
ProgramOptions po;
|
||||
po.setOptionPrefix(ProgramOptions::SINGLE_DASH);
|
||||
po.registerOption("single", ProgramOptions::SINGLE_VALUE);
|
||||
po.registerOption("multi", ProgramOptions::MULTI_VALUE);
|
||||
|
||||
String cmdLine("MyExe -single 1 -multi A -multi A B -single 2");
|
||||
std::vector<String> cmdLineArgs = cmdLine.split();
|
||||
ASSERT_TRUE(po.parse(cmdLineArgs));
|
||||
|
||||
ASSERT_TRUE(po.hasOption("single"));
|
||||
ASSERT_EQ(1, po.valueCount("single"));
|
||||
ASSERT_TRUE(po.combinedValues("single") == "2");
|
||||
|
||||
ASSERT_TRUE(po.hasOption("multi"));
|
||||
ASSERT_EQ(2, po.valueCount("multi"));
|
||||
ASSERT_TRUE(po.combinedValues("multi") == "A B");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, RepeatOptionsCombining)
|
||||
{
|
||||
ProgramOptions po;
|
||||
po.setOptionPrefix(ProgramOptions::SINGLE_DASH);
|
||||
po.registerOption("single", ProgramOptions::SINGLE_VALUE, ProgramOptions::COMBINE_REPEATED);
|
||||
po.registerOption("multi", ProgramOptions::MULTI_VALUE, ProgramOptions::COMBINE_REPEATED);
|
||||
|
||||
String cmdLine("MyExe -single 1 -multi A -multi A B -single 2");
|
||||
std::vector<String> cmdLineArgs = cmdLine.split();
|
||||
ASSERT_TRUE(po.parse(cmdLineArgs));
|
||||
|
||||
ASSERT_TRUE(po.hasOption("single"));
|
||||
ASSERT_EQ(2, po.valueCount("single"));
|
||||
ASSERT_TRUE(po.combinedValues("single") == "1 2");
|
||||
|
||||
ASSERT_TRUE(po.hasOption("multi"));
|
||||
ASSERT_EQ(3, po.valueCount("multi"));
|
||||
ASSERT_TRUE(po.combinedValues("multi") == "A A B");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, RealWorld_1)
|
||||
{
|
||||
ProgramOptions po;
|
||||
po.registerOption("calculate", "", "", ProgramOptions::NO_VALUE);
|
||||
po.registerOption("size", "<x> <y>", "", ProgramOptions::MULTI_VALUE);
|
||||
po.registerOption("replace", "<id> <fileName>", "", ProgramOptions::MULTI_VALUE);
|
||||
po.registerOption("search", "<filters>", "", ProgramOptions::MULTI_VALUE);
|
||||
po.registerOption("outFile", "<fileName>", "", ProgramOptions::SINGLE_VALUE);
|
||||
|
||||
String cmdLine("MyExe fileName.txt --size 10 20 --calculate --outfile outfile.txt --replace 99 replace.txt --search *.txt case???.bin");
|
||||
std::vector<String> cmdLineArgs = cmdLine.split();
|
||||
ASSERT_TRUE(po.parse(cmdLineArgs));
|
||||
|
||||
ASSERT_EQ(1, po.positionalParameters().size());
|
||||
EXPECT_TRUE(po.positionalParameters()[0] == "fileName.txt");
|
||||
|
||||
ASSERT_TRUE(po.hasOption("calculate"));
|
||||
|
||||
{
|
||||
ASSERT_TRUE(po.hasOption("size"));
|
||||
std::vector<String> vals = po.values("size");
|
||||
ASSERT_EQ(2, vals.size());
|
||||
int x = vals[0].toInt();
|
||||
int y = vals[1].toInt();
|
||||
EXPECT_EQ(10, x);
|
||||
EXPECT_EQ(20, y);
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_TRUE(po.hasOption("replace"));
|
||||
std::vector<String> vals = po.values("replace");
|
||||
ASSERT_EQ(2, vals.size());
|
||||
int id = vals[0].toInt();
|
||||
String fileName = vals[1];
|
||||
EXPECT_EQ(99, id);
|
||||
EXPECT_TRUE(fileName == "replace.txt");
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_TRUE(po.hasOption("search"));
|
||||
std::vector<String> vals = po.values("search");
|
||||
ASSERT_EQ(2, vals.size());
|
||||
EXPECT_TRUE(vals[0] == "*.txt");
|
||||
EXPECT_TRUE(vals[1] == "case???.bin");
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_TRUE(po.hasOption("outFile"));
|
||||
String fileName = po.combinedValues("outFile");
|
||||
EXPECT_TRUE(fileName == "outfile.txt");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, RealWorld_2)
|
||||
{
|
||||
ProgramOptions po;
|
||||
po.setOptionPrefix(ProgramOptions::SLASH);
|
||||
po.registerOption("version", "", "", ProgramOptions::NO_VALUE);
|
||||
po.registerOption("width", "<width>", "", ProgramOptions::SINGLE_VALUE);
|
||||
po.registerOption("outFiles", "<fileNames>", "", ProgramOptions::MULTI_VALUE, ProgramOptions::COMBINE_REPEATED);
|
||||
|
||||
String cmdLine("MyExe file1.txt file2.txt /width 25 /outFiles res\\out1.txt res\\out2.txt /version /outFiles c:\\out3.txt");
|
||||
std::vector<String> cmdLineArgs = cmdLine.split();
|
||||
ASSERT_TRUE(po.parse(cmdLineArgs));
|
||||
|
||||
ASSERT_EQ(2, po.positionalParameters().size());
|
||||
EXPECT_TRUE(po.positionalParameters()[0] == "file1.txt");
|
||||
EXPECT_TRUE(po.positionalParameters()[1] == "file2.txt");
|
||||
|
||||
ASSERT_TRUE(po.hasOption("version"));
|
||||
|
||||
{
|
||||
ASSERT_TRUE(po.hasOption("width"));
|
||||
int width = po.combinedValues("width").toInt();
|
||||
EXPECT_EQ(25, width);
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_TRUE(po.hasOption("outFiles"));
|
||||
std::vector<String> vals = po.values("outFiles");
|
||||
ASSERT_EQ(3, vals.size());
|
||||
EXPECT_TRUE(vals[0] == "res\\out1.txt");
|
||||
EXPECT_TRUE(vals[1] == "res\\out2.txt");
|
||||
EXPECT_TRUE(vals[2] == "c:\\out3.txt");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ProgramOptionsTest, UsageText)
|
||||
{
|
||||
ProgramOptions po;
|
||||
po.registerOption("calculate", "", "Do the calculation.", ProgramOptions::NO_VALUE);
|
||||
po.registerOption("size", "<x> <y>", "Set widow size.", ProgramOptions::MULTI_VALUE);
|
||||
po.registerOption("replace", "<id> <filName>", "Replace file for case with specified id.", ProgramOptions::MULTI_VALUE);
|
||||
po.registerOption("search", "<filters>", "Search filters", ProgramOptions::MULTI_VALUE);
|
||||
po.registerOption("outFile", "<fileName>", "Output file name", ProgramOptions::SINGLE_VALUE);
|
||||
|
||||
String usageText = po.usageText(60);
|
||||
cvf::Trace::show(usageText);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user