// ____ ______ __ // / __ \ / ____// / // / /_/ // / / / // / ____// /___ / /___ 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 #include #include #include 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). * * 1. Parametric Arguments * * Parametric arguments specify \e modifiers or parameter values of different * types to their receiving processes. Syntactically, parametric arguments are * formalized as: * * -<arg_id>[<arg_value>] * * where the starting hypen character '-' is the standard parameter * prefix. <arg_id> is the argument identifier and * <arg_value> is an optional argument value specification. For * example, in the following parametric arguments: * * -n=17 --use-all-processors * * 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. * * 1.1 Literal Arguments * * 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: * * -c -x=10 -b="none" --verbose * * '-c' and '--verbose' are literal arguments. * * 1.2 Switch Arguments * * Switch arguments are parametric arguments that can only have a boolean * \e enabled/disabled state. Switch arguments are of the form: * * -<arg_id>+|- * * where the + suffix means 'enabled' and the - suffix means 'disabled'. * For example, here are some switch arguments: * * -u+ -color- --mySwitchArgument+ * * 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: * * -<arg_id>[+|-] * * indicating that the + and - suffixes are optional. * * 1.3 Numeric Arguments * * A numeric argument has an integer or floating-point numeric value. Numeric * arguments are formalized as: * * -<arg_id>=<numeric_constant> * * where <numeric_constant> 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. * * 1.4 %String Arguments * * A string argument has a literal value represented as a string of ISO 8859-1 * characters. String arguments are formalized as: * * -<arg_id>=<string_constant> * * where <string_constant> is any sequence of ISO 8859-1 characters, * optionally enclosed by double quotes. For example: * * -s=foo -s1="bar" * * are two string arguments with 'foo' and 'bar' values, respectively. When the * <string_constant> string includes white spaces, the enclosing quotes are * not optional, as in: * * -aStringArg="this is a string literal" * * or otherwise the above sequence would be interpreted as a single string * argument (aStringArg=this) and four additional, non-parametric arguments. * * 2. Non-Parametric Arguments * * Non-parametric arguments specify \e objects that their receiving processes * can act on or use in any way. Non-parametric arguments are formalized as: * * <arg_value> * * where <arg_value> is any sequence of ISO 8859-1 characters. Note that the * absence of a standard parameter prefix (the hypen character, '-') * characterizes non-parametric arguments. For example, in the following * arguments: * * -mode="auto" *.js -z foo.scp * * '*.js' and 'foo.scp' are two non-parametric arguments. * * Each non-parametric argument can be expanded into a list of items. * 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 parametric argument, or an empty string * otherwise. */ String Id() const { return id; } /*! * Returns true iff this argument has been parsed and it is a * non-parametric argument, also known as an item * argument. */ 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 literal * argument. */ bool IsLiteral() const { return type == literal_arg; } /*! * Returns true iff this argument has been parsed and it is a switch * argument. */ bool IsSwitch() const { return type == switch_arg; } /*! * Returns the switch state of this argument, if it has been parsed and it * is a switch argument, or false otherwise. */ bool SwitchState() const { return asSwitch; } /*! * Returns true iff this argument has been parsed and it is a numeric * argument. */ bool IsNumeric() const { return type == numeric_arg; } /*! * Returns the numeric value of this argument, if it has been parsed and it * is a numeric argument, or zero otherwise. */ double NumericValue() const { return asNumeric; } /*! * Returns true iff this argument has been parsed and it is a string * argument. */ bool IsString() const { return type == string_arg; } /*! * Returns the string value of this argument, if it has been parsed and it * is a string argument, 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 ArgumentList; // ---------------------------------------------------------------------------- /*! * \namespace pcl::ArgumentItemMode * \brief Non-parametric argument parsing modes. * * * * * * *
ArgumentItemMode::Ignore Consider non-parametric items as literal items (plain strings)
ArgumentItemMode::AsFiles Non-parametric items are file paths
ArgumentItemMode::AsViews Non-parametric items are view identifiers
ArgumentItemMode::NoItems Non-parametric items are not allowed
* * \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. * * * * * * *
ArgumentOption::AllowWildcards Allow wildcard characters (*?) in non-parametric items
ArgumentOption::NoPreviews Don't allow preview specifications (with the '->' standard separator)
ArgumentOption::RecursiveDirSearch Perform recursive directory searches for wild path specifications
ArgumentOption::RecursiveSearchArgs Use standard arguments to toggle recursive directory searching
* * \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 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: * * [<arg_list>] [<item_list>] * * where: * * <item_list> * Is a sequence <item> [<item_list>] * * <item> * Is a non-parametric (or "item") argument. If file parsing is active * (see the \a mode parameter below), each item will be parsed as a file path * specification. If view parsing 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. * * <arg_list> * Is a sequence <arg> [<arg_list>] * * <arg> * 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 * * * * * * * * * *
ArgumentItemMode::Ignore. Non-parametric arguments will * not be parsed and will be passed unchanged.
ArgumentItemMode::AsFiles. 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.
ArgumentItemMode::AsViews. 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.
ArgumentItemMode::NoItems. 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.
\n\n * * \param options This is an OR'ed combination of flags from the * ArgumentOption enumeration:\n * \n * * * * * * * * * *
ArgumentItemMode::AllowWildcards. 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.
ArgumentItemMode::NoPreviews. 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.
ArgumentItemMode::RecursiveDirSearch. 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).
ArgumentItemMode::RecursiveSearchArgs. 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 --r[+|-], 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 --r toggle argument: * * *.cpp --r *.h *.png --r- *.exe * * In the example above, *.h and *.png will be * searched recursively through the entire directory tree rooted at * the current directory, but *.cpp and *.exe files * will only be searched for in the current directory.
* * 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 * --r[+|-] 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: * * $<env_name> * * where <env_name> is any sequence of alphabetic, decimal, or underscore * characters. If <env_name> corresponds to an existing environment * variable of the calling process, the entire $<env_name> 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