// -*- C++ -*- //============================================================================= /** * @file Arg_Shifter.h * * @author Seth Widoff */ //============================================================================= #ifndef ACE_ARG_SHIFTER_H #define ACE_ARG_SHIFTER_H #include /**/ "ace/pre.h" #include /**/ "ace/ACE_export.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Global_Macros.h" ACE_BEGIN_VERSIONED_NAMESPACE_DECL /** * @class ACE_Arg_Shifter_T * * @brief This ADT operates on a specified set of arguments (@a argv). * As known arguments are scanned, they are shifted to the back of the * @a argv vector, so deeper levels of argument parsing can locate the yet * unprocessed arguments at the beginning of the vector. * * Nomenclature: * argument - a member of the argv array * option - an argument starting with '-' * flag - synonym for "option" * parameter value - an argument not starting with '-' * parameter - synonym for "parameter value" * * The @c ACE_Arg_Shifter copies the pointers of the @a argv vector * into a temporary array, emptying the original. As the @c ACE_Arg_Shifter * iterates over the temporary array, it places known arguments in the rear * of the original array and places the unknown ones in the beginning of the * original array. It modifies argc to be the number of unknown arguments, * so it looks to the caller as if the original array contains only unknown * arguments. So, after @c ACE_Arg_Shifter has visited all the arguments * in the temporary array, the original @a argv array appears to contain * only the unknown arguments in their original order (but it actually has * all the known arguments, too, beyond argc). */ template class ACE_Arg_Shifter_T { public: /** * Initialize the ACE_Arg_Shifter to the vector over which to * iterate. Optionally, also provide the temporary array for * use in shifting the arguments. If ACE_Arg_Shifter must allocate * the temporary vector internally and dynamic allocation fails, the * ACE_Arg_Shifter will set all indicators to end of the vector, * forbidding iteration. Following iteration over @a argv, the * @a argc value will be updated to contain the number of * unconsumed arguments. * @param argc The number of strings in @a argv. @a argc will be * updated to reflect the number of unconsumed arguments. * @param argv The argument vector to shift. The string pointers in * the vector will be reordered to place the @a argc unconsumed * arguments at the front of the vector. * @param temp A vector of @c CHAR_TYPE pointers at least @a argc * elements long. The vector will be used for argument shifting as * the specified @a argv vector is consumed. The vector must not * be modified while this object exists. If this argument is 0 * (the default) the object will allocate and free the temporary * vector transparently. */ ACE_Arg_Shifter_T (int &argc, const CHAR_TYPE **argv, const CHAR_TYPE **temp = 0); /// Same behavior as the preceding constructor, but without the /// "const" qualifier. ACE_Arg_Shifter_T (int &argc, CHAR_TYPE **argv, CHAR_TYPE **temp = 0); /// Destructor. ~ACE_Arg_Shifter_T (); /// Get the current head of the vector. const CHAR_TYPE *get_current () const; /** * If the @a flag matches the current_arg of arg shifter * this method will attempt to return the associated * parameter value * * Safe to call without checking that a current arg exists * * In the following examples, a pointer to the char* "value" is returned * * eg: main -foobar value, main -FooBar value * main -FOOBARvalue * * all of the above will match the @a flag == -FooBar * and will return a char* to "value" * * main -foobar 4 would succeed and return a char* to "4" * main -foobar -4 does not succeed (-4 is not a parameter) * but instead, would return 0 * * 0 is returned: * If the current argument does not match flag * If there is no parameter found after a 'matched' flag * * If the flag is matched and the flag and parameter DO NOT RUN * together, the flag is consumed, the parameter is returned, * and the new current argument is the parameter value. * ie '-foobarflag VALUE' leaves the new cur arg == "VALUE" * * If the flag is matched and the flag and parameter RUN * together '-foobarflagVALUE', the flag is NOT consumed * and the cur arg is left pointing to the entire flag/value pair */ const CHAR_TYPE *get_the_parameter (const CHAR_TYPE *flag); /** * Check if the current argument matches (case insensitive) @a flag * * ------------------------------------------------------------ * * Case A: Perfect Match (case insensitive) * 0 is returned. * * ie: when current_arg = "-foobar" or "-FOOBAR" or "-fooBAR" * this->cur_arg_strncasecmp ("-FooBar"); * will return 0 * * ------------------------------------------------------------ * * Case B: Perfect Match (case insensitive) but the current_arg * is longer than the flag. Returns a number equal to the index * in the char* indicating the start of the extra characters * after any initial spaces (see below). * * ie: when current_arg = "-foobar98023" * this->cur_arg_strncasecmp ("-FooBar"); * will return 7 * * Spaces separating the flag from its value (that are still part * of the same argv element) are counted as part of the return value * * ie: when current_arg = "-foobar 98023" * this->cur_arg_strncasecmp ("-FooBar"); * will return 8 * * Notice: this number will always be > 0 * * ------------------------------------------------------------ * * Case C: If neither of Case A or B is met (no match) * then -1 is returned */ int cur_arg_strncasecmp (const CHAR_TYPE *flag); /// Consume @a number argument(s) by sticking them/it on the end of /// the vector. int consume_arg (int number = 1); /// Place @a number arguments in the same relative order ahead of the /// known arguments in the vector. int ignore_arg (int number = 1); /// Returns the number of args left to see in the vector. int is_anything_left () const; /// Returns 1 if there's a next item in the vector and it begins with /// '-'. int is_option_next () const; /// Returns 1 if there's a next item in the vector and it doesn't /// begin with '-'. int is_parameter_next () const; /// Returns the number of irrelevant args seen. int num_ignored_args () const; private: /// Copy Constructor should not be used. ACE_Arg_Shifter_T (const ACE_Arg_Shifter_T &) = delete; /// Assignment '=' operator should not be used. ACE_Arg_Shifter_T operator= (const ACE_Arg_Shifter_T &) = delete; /// Refactor the constructor logic. void init (); /// The size of the argument vector. int &argc_; /// The size of argv_. int total_size_; /// The temporary array over which we traverse. const CHAR_TYPE **temp_; /// The array in which the arguments are reordered. const CHAR_TYPE **argv_; /// The element in we're currently examining. int current_index_; /// The index of in which we'll stick the next unknown /// argument. int back_; /// The index of in which we'll stick the next known /// argument. /** This is not really the "front" at all. It's the point after * which the unknown arguments end and at which the known arguments begin. */ int front_; }; typedef ACE_Arg_Shifter_T ACE_Arg_Shifter; ACE_END_VERSIONED_NAMESPACE_DECL #include "ace/Arg_Shifter.cpp" #include /**/ "ace/post.h" #endif /* ACE_ARG_SHIFTER_H */