Files
tenmon/3rdparty/include/pcl/Arguments.h
T
2022-04-12 08:17:18 +02:00

682 lines
24 KiB
C++

// ____ ______ __
// / __ \ / ____// /
// / /_/ // / / /
// / ____// /___ / /___ PixInsight Class Library
// /_/ \____//_____/ PCL 2.4.23
// ----------------------------------------------------------------------------
// pcl/Arguments.h - Released 2022-03-12T18:59:29Z
// ----------------------------------------------------------------------------
// This file is part of the PixInsight Class Library (PCL).
// PCL is a multiplatform C++ framework for development of PixInsight modules.
//
// Copyright (c) 2003-2022 Pleiades Astrophoto S.L. All Rights Reserved.
//
// Redistribution and use in both source and binary forms, with or without
// modification, is permitted provided that the following conditions are met:
//
// 1. All redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. All redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
// of their contributors, may be used to endorse or promote products derived
// from this software without specific prior written permission. For written
// permission, please contact info@pixinsight.com.
//
// 4. All products derived from this software, in any form whatsoever, must
// reproduce the following acknowledgment in the end-user documentation
// and/or other materials provided with the product:
//
// "This product is based on software from the PixInsight project, developed
// by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
//
// Alternatively, if that is where third-party acknowledgments normally
// appear, this acknowledgment must be reproduced in the product itself.
//
// THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
// INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
// DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// ----------------------------------------------------------------------------
#ifndef __PCL_Arguments_h
#define __PCL_Arguments_h
/// \file pcl/Arguments.h
#include <pcl/Defs.h>
#include <pcl/Flags.h>
#include <pcl/String.h>
#include <pcl/StringList.h>
namespace pcl
{
// ----------------------------------------------------------------------------
/*!
* \defgroup argument_parsing Argument Parsing Routines and Utilities
*/
// ----------------------------------------------------------------------------
/*!
* \class Argument
* \brief A command-line argument
*
* %Argument implements a command-line argument that can be used with the
* ParseArguments() function.
*
* Command-line arguments can be \e parametric and \e non-parametric
* arguments (also known as \e item \e arguments).
*
* <b>1. Parametric Arguments</b>
*
* Parametric arguments specify \e modifiers or parameter values of different
* types to their receiving processes. Syntactically, parametric arguments are
* formalized as:
*
* <tt>-&lt;arg_id&gt;[&lt;arg_value&gt;]</tt>
*
* where the starting hypen character '-' is the <em>standard parameter
* prefix.</em> &lt;arg_id&gt; is the <em>argument identifier</em> and
* &lt;arg_value&gt; is an optional <em>argument value</em> specification. For
* example, in the following parametric arguments:
*
* <tt>-n=17 --use-all-processors</tt>
*
* the argument identifiers are 'n' and '-use-all-processors', respectively,
* and '=17' is an argument value specification.
*
* We consider four types of parametric arguments: \e literal, \e switch,
* \e numeric and \e string arguments.
*
* <b>1.1 Literal Arguments</b>
*
* Literal arguments are parametric arguments that don't have a particular
* value. They are modifiers that act as functions of their existence. For
* example, in the following arguments:
*
* <tt>-c -x=10 -b="none" --verbose</tt>
*
* '-c' and '--verbose' are literal arguments.
*
* <b>1.2 Switch Arguments</b>
*
* Switch arguments are parametric arguments that can only have a boolean
* \e enabled/disabled state. Switch arguments are of the form:
*
* <tt>-&lt;arg_id&gt;+|-</tt>
*
* where the + suffix means 'enabled' and the - suffix means 'disabled'.
* For example, here are some switch arguments:
*
* <tt>-u+ -color- --mySwitchArgument+</tt>
*
* It is customary to allow the use of switch arguments also as literal
* arguments. When switch arguments are used as literal arguments, a default
* 'enabled' or 'disabled' state is assumed, depending on the functionality and
* purpose of each argument. When switch arguments can also be literal, they
* are formalized as:
*
* <tt>-&lt;arg_id&gt;[+|-]</tt>
*
* indicating that the + and - suffixes are optional.
*
* <b>1.3 Numeric Arguments</b>
*
* A numeric argument has an integer or floating-point numeric value. Numeric
* arguments are formalized as:
*
* <tt>-&lt;arg_id&gt;=&lt;numeric_constant&gt;</tt>
*
* where &lt;numeric_constant&gt; is a valid representation of an integer or
* floating-point real constant, following the applicable syntax rules of the C
* language. Integer constants can have the '0x' standard prefix to indicate
* hexadecimal values.
*
* <b>1.4 %String Arguments</b>
*
* A string argument has a literal value represented as a string of ISO 8859-1
* characters. String arguments are formalized as:
*
* <tt>-&lt;arg_id&gt;=&lt;string_constant&gt;</tt>
*
* where &lt;string_constant&gt; is any sequence of ISO 8859-1 characters,
* optionally enclosed by double quotes. For example:
*
* <tt>-s=foo -s1="bar"</tt>
*
* are two string arguments with 'foo' and 'bar' values, respectively. When the
* &lt;string_constant&gt; string includes white spaces, the enclosing quotes are
* not optional, as in:
*
* <tt>-aStringArg="this is a string literal"</tt>
*
* or otherwise the above sequence would be interpreted as a single string
* argument (aStringArg=this) and four additional, non-parametric arguments.
*
* <b>2. Non-Parametric Arguments</b>
*
* Non-parametric arguments specify \e objects that their receiving processes
* can act on or use in any way. Non-parametric arguments are formalized as:
*
* <tt>&lt;arg_value&gt;</tt>
*
* where &lt;arg_value&gt; is any sequence of ISO 8859-1 characters. Note that the
* absence of a <em>standard parameter prefix</em> (the hypen character, '-')
* characterizes non-parametric arguments. For example, in the following
* arguments:
*
* <tt>-mode="auto" *.js -z foo.scp</tt>
*
* '*.js' and 'foo.scp' are two non-parametric arguments.
*
* Each non-parametric argument can be expanded into a <em>list of items.</em>
* For example, the '*.js' argument above would be expanded into a list of all
* files with the .js suffix in the current directory, provided that the
* argument is parsed as a wild file path specification.
*
* \sa ParseArguments(), ArgumentItemMode, ArgumentOption
*
* \ingroup argument_parsing
*/
class PCL_CLASS Argument
{
public:
/*!
* Constructs an empty %Argument object.
*/
Argument()
{
Initialize();
}
/*!
* Constructs an %Argument object and parses the specified \a argv string.
*/
Argument( const String& argv )
{
Parse( argv.c_str() );
}
/*!
* Constructs an %Argument object and parses the specified \a argv string.
*/
Argument( const char16_type* argv )
{
Parse( argv );
}
/*!
* Constructs an %Argument object and interprets that the specified \a argv
* string corresponds to a non-parametric argument corresponding to the
* \a items list of items.
*/
Argument( const String& argv, const StringList& items )
{
type = item_arg;
token = argv;
asItems = items;
}
/*!
* Copy constructor.
*/
Argument( const Argument& ) = default;
/*!
* Copy assignment operator. Returns a reference to this object.
*/
Argument& operator =( const Argument& ) = default;
/*!
* Equality operator. Returns true if this %Argument object is equal to the
* specified \a x instance.
*/
bool operator ==( const Argument& x ) const
{
if ( id == x.id && type == x.type )
{
if ( IsLiteral() || !IsValid() )
return true;
if ( IsNumeric() )
return asNumeric == x.asNumeric;
if ( IsString() )
return asString == x.asString;
if ( IsSwitch() )
return asSwitch == x.asSwitch;
if ( IsItemList() )
return asItems == x.asItems;
}
return false;
}
/*!
* Returns true iff this argument has successfully parsed a token string.
*/
bool IsValid() const
{
return type != invalid_arg;
}
/*!
* Returns the token string corresponding to this argument. The token is the
* exact string that has been parsed by this %Argument instance. If no token
* has been parsed by this instance, an empty string is returned.
*/
String Token() const
{
return token;
}
/*!
* Returns the argument's parameter identifier, if this argument has been
* parsed and it is a <em>parametric argument</em>, or an empty string
* otherwise.
*/
String Id() const
{
return id;
}
/*!
* Returns true iff this argument has been parsed and it is a
* <em>non-parametric argument</em>, also known as an <em>item
* argument.</em>
*/
bool IsItemList() const
{
return type == item_arg;
}
/*!
* Returns a reference to the (constant) list of items that have been
* generated after expansion of a non-parametric argument. The returned list
* cannot be modified, and it's empty if this argument is parametric, or if
* it has not been parsed yet.
*/
const StringList& Items() const
{
return asItems;
}
/*!
* Returns a reference to the list of items that have been generated after
* expansion of a non-parametric argument. The returned list can be freely
* modified, and it's empty if this argument is parametric, or if it has not
* been parsed yet.
*/
StringList& Items()
{
return asItems;
}
/*!
* Returns true iff this argument has been parsed and it is a <em>literal
* argument</em>.
*/
bool IsLiteral() const
{
return type == literal_arg;
}
/*!
* Returns true iff this argument has been parsed and it is a <em>switch
* argument</em>.
*/
bool IsSwitch() const
{
return type == switch_arg;
}
/*!
* Returns the switch state of this argument, if it has been parsed and it
* is a <em>switch argument</em>, or false otherwise.
*/
bool SwitchState() const
{
return asSwitch;
}
/*!
* Returns true iff this argument has been parsed and it is a <em>numeric
* argument</em>.
*/
bool IsNumeric() const
{
return type == numeric_arg;
}
/*!
* Returns the numeric value of this argument, if it has been parsed and it
* is a <em>numeric argument</em>, or zero otherwise.
*/
double NumericValue() const
{
return asNumeric;
}
/*!
* Returns true iff this argument has been parsed and it is a <em>string
* argument</em>.
*/
bool IsString() const
{
return type == string_arg;
}
/*!
* Returns the string value of this argument, if it has been parsed and it
* is a <em>string argument</em>, or an empty string otherwise.
*/
String StringValue() const
{
return asString;
}
private:
enum arg_type { invalid_arg = -1, item_arg, literal_arg, switch_arg, numeric_arg, string_arg };
String token; // argument token
String id; // argument id
arg_type type; // argument type, or invalid
StringList asItems; // list of non-parameters (e.g. file names or view ids)
bool asSwitch; // logical state of a switch argument
double asNumeric; // value of a numerical argument
String asString; // value of a string argument
void Initialize()
{
token.Clear();
id.Clear();
type = invalid_arg;
asItems.Clear();
asSwitch = false;
asNumeric = 0;
asString.Clear();
}
void Parse( const char16_type* );
};
/*!
* \class pcl::ArgumentList
* \brief A dynamic array of command-line arguments
* \ingroup argument_parsing
*/
typedef Array<Argument> ArgumentList;
// ----------------------------------------------------------------------------
/*!
* \namespace pcl::ArgumentItemMode
* \brief Non-parametric argument parsing modes.
*
* <table border="1" cellpadding="4" cellspacing="0">
* <tr><td>ArgumentItemMode::Ignore</td> <td>Consider non-parametric items as literal items (plain strings)</td></tr>
* <tr><td>ArgumentItemMode::AsFiles</td> <td>Non-parametric items are file paths</td></tr>
* <tr><td>ArgumentItemMode::AsViews</td> <td>Non-parametric items are view identifiers</td></tr>
* <tr><td>ArgumentItemMode::NoItems</td> <td>Non-parametric items are not allowed</td></tr>
* </table>
*
* \ingroup argument_parsing
*/
namespace ArgumentItemMode
{
enum value_type
{
Ignore, // Consider non-parametric items as literal items (plain strings)
AsFiles, // Non-parametric items are file paths
AsViews, // Non-parametric items are view identifiers
NoItems, // Non-parametric items are not allowed
};
}
/*!
* \class pcl::argument_item_mode
* \brief Represents an ArgumentItemMode enumerated value.
* \ingroup argument_parsing
*/
typedef ArgumentItemMode::value_type argument_item_mode;
// ----------------------------------------------------------------------------
/*!
* \namespace pcl::ArgumentOption
* \brief Working options affecting how non-parametric arguments are
* interpreted.
*
* <table border="1" cellpadding="4" cellspacing="0">
* <tr><td>ArgumentOption::AllowWildcards</td> <td>Allow wildcard characters (*?) in non-parametric items</td></tr>
* <tr><td>ArgumentOption::NoPreviews</td> <td>Don't allow preview specifications (with the '->' standard separator)</td></tr>
* <tr><td>ArgumentOption::RecursiveDirSearch</td> <td>Perform recursive directory searches for wild path specifications</td></tr>
* <tr><td>ArgumentOption::RecursiveSearchArgs</td> <td>Use standard arguments to toggle recursive directory searching</td></tr>
* </table>
*
* \ingroup argument_parsing
*/
namespace ArgumentOption
{
enum mask_type
{
AllowWildcards = 0x00000001, // Allow wildcard characters (*?) in non-parametric items
NoPreviews = 0x00000002, // Don't allow preview specifications (with the '->' standard separator)
RecursiveDirSearch = 0x00000004, // Perform recursive directory searches for wild path specifications
RecursiveSearchArgs = 0x00000008, // Use standard arguments to toggle recursive directory searching
};
}
/*!
* \class pcl::ArgumentOptions
* \brief A combination of ArgumentOption flags
* \ingroup argument_parsing
*/
typedef Flags<ArgumentOption::mask_type> ArgumentOptions;
// ----------------------------------------------------------------------------
// The implementation of ExtractArguments() is slightly different in core.
#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
} // pcl
using namespace pcl;
namespace pi
{
#endif
/*!
* Extracts a sequence of command-line arguments of the form:
*
* <tt>[&lt;arg_list&gt;] [&lt;item_list&gt;]</tt>
*
* where:
*
* <tt>&lt;item_list&gt;</tt>
* Is a sequence <tt>&lt;item&gt; [&lt;item_list&gt;]</tt>
*
* <tt>&lt;item&gt;</tt>
* Is a non-parametric (or "item") argument. If <em>file parsing</em> is active
* (see the \a mode parameter below), each item will be parsed as a file path
* specification. If <em>view parsing</em> is active, items will be considered
* as view identifiers. In both cases, each item may include wildcards to
* define a search pattern, which will be automatically expanded into a
* sequence of actual file paths or view identifiers.
*
* <tt>&lt;arg_list&gt;</tt>
* Is a sequence <tt>&lt;arg&gt; [&lt;arg_list&gt;]</tt>
*
* <tt>&lt;arg&gt;</tt>
* Is a parametric argument (see the documentation for the Argument class for a
* complete description).
*
* \param argv The list of input argument tokens that will be parsed.\n\n
*
* \param mode Indicates how non-parametric items will be handled by this
* function. \a mode must have one of the following values:\n
* \n
* <table border="1" cellpadding="4" cellspacing="0">
* <tr>
* <td><b>ArgumentItemMode::Ignore</b>. Non-parametric arguments will
* not be parsed and will be passed unchanged.</td></tr>
* <tr>
* <td><b>ArgumentItemMode::AsFiles</b>. Each non-parametric argument
* is interpreted as a file path specification. Note that neither
* validity of file paths nor the existence of actual files are
* verified.</td></tr>
* <tr>
* <td><b>ArgumentItemMode::AsViews</b>. Each non-parametric argument
* is interpreted and parsed as a view identifier specification. Note
* that only validity of view identifiers is verified, not the
* existence of actual views with such identifiers.</td></tr>
* <tr>
* <td><b>ArgumentItemMode::NoItems</b>. This mode disallows
* non-parametric arguments. An exception is thrown if a
* non-parametric item is found in the input sequence of \a argv
* elements.</td></tr>
* </table>\n\n
*
* \param options This is an OR'ed combination of flags from the
* ArgumentOption enumeration:\n
* \n
* <table border="1" cellpadding="4" cellspacing="0">
* <tr>
* <td><b>ArgumentItemMode::AllowWildcards</b>. If this flag is
* included, each file argument containing wildcards ('*' and '?'
* characters) will originate a search for all files matching the
* specified wildcard pattern. If view arguments are being considered,
* each wildcard item will be expanded into a list of matching view
* identifiers.</td></tr>
* <tr>
* <td><b>ArgumentItemMode::NoPreviews</b>. This flag prevents the
* inclusion of preview identifiers in the output arguments set. If a
* preview specification (imageId->previewId) is found and this flag
* is active, an exception is thrown.</td></tr>
* <tr>
* <td><b>ArgumentItemMode::RecursiveDirSearch</b>. This flag only
* makes sense along with the ArgumentItemMode::AsFiles mode. If used,
* this flag will originate recursive directory searches for all file
* path specifications containing wildcards. Note that the behavior of
* this flag can be altered by the RecursiveSearchArgs flag (see
* below).</td></tr>
* <tr>
* <td><b>ArgumentItemMode::RecursiveSearchArgs</b>. This flag only
* makes sense along with the ArgumentItemMode::AsFiles mode and the
* RecursiveDirSearch flag (see above). If used, recursive directory
* searches will be controlled by a special toggle argument. All
* instances of this argument will be processed automatically by the
* routine and will not be included in the output arguments list. By
* default, this argument is <tt>--r[+|-]</tt>, but it can be changed
* by calling the SetRecursiveDirSearchArgument() static function.\n
* \n
* Example of wild path argument specifications with recursive search
* through the standard <tt>--r</tt> toggle argument:
*
* <tt>*.cpp --r *.h *.png --r- *.exe</tt>
*
* In the example above, <tt>*.h</tt> and <tt>*.png</tt> will be
* searched recursively through the entire directory tree rooted at
* the current directory, but <tt>*.cpp</tt> and <tt>*.exe</tt> files
* will only be searched for in the current directory.</td></tr>
* </table>
*
* This function generates a ParseError exception when it encounters an error
* while parsing the sequence of input arguments.
*
* Returns a list with all the arguments extracted from the input \a argv
* sequence as instances of the Argument class. If non-parametric arguments are
* being interpreted as file paths, each non-parametric item is expanded to its
* corresponding full file path. If non-parametric arguments are being parsed
* as view identifiers, each non-parametric item is replaced (if appropriate)
* by its full view identifier. Otherwise, non-parametric items are returned
* unchanged.
*
* \ingroup argument_parsing
*/
ArgumentList PCL_FUNC ExtractArguments( const StringList& argv,
argument_item_mode mode = ArgumentItemMode::Ignore,
ArgumentOptions options = ArgumentOptions() );
#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
} // pi
namespace pcl
{
#endif
/*!
* Returns the identifier of the argument used by ExtractArguments() for
* automatic toggle of recursive directory searches. By default, this is the
* <tt>--r[+|-]</tt> argument.
*
* \ingroup argument_parsing
*/
String PCL_FUNC RecursiveDirSearchArgument();
/*!
* Sets the identifier of the argument used by ExtractArguments() for
* automatic toggle of recursive directory searches.
*
* \param id New identifier for the automatic recursive search argument.
* N.B.: When specifying this argument, don't include the '-'
* standard parameter prefix.
*
* \ingroup argument_parsing
*/
void PCL_FUNC SetRecursiveDirSearchArgument( const String& id );
/*!
* Auxiliary directory search routine used by ExtractArguments().
*
* Returns a list of full file paths corresponding to a template wild file
* specification (\a filePath), optionally recursing the directory tree,
* starting from the directory specified in \a filePath.
*
* \ingroup argument_parsing
*/
StringList PCL_FUNC SearchDirectory( const String& filePath, bool recursive = false );
/*!
* Returns a copy of a source string \a s where all references to environment
* variables have been replaced with their corresponding values.
*
* This function finds all occurrences of environment variables of the form:
*
* $&lt;env_name&gt;
*
* where &lt;env_name&gt; is any sequence of alphabetic, decimal, or underscore
* characters. If &lt;env_name&gt; corresponds to an existing environment
* variable of the calling process, the entire $&lt;env_name&gt; sequence is
* replaced with the variable's value. References to nonexistent environment
* variables, as well as empty references (isolated $ characters), are
* replaced with an empty string (removed).
*
* This function works recursively: it can replace environment variables
* inside the values of environment variables. The routine performs
* replacements recursively until no $ character is found in the string.
*
* \ingroup argument_parsing
*/
String PCL_FUNC ReplaceEnvironmentVariables( const String& s );
// ----------------------------------------------------------------------------
} // pcl
#endif // __PCL_Arguments_h
// ----------------------------------------------------------------------------
// EOF pcl/Arguments.h - Released 2022-03-12T18:59:29Z