ncbiargs.hpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:40k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbiargs.hpp,v $
  4.  * PRODUCTION Revision 1000.0  2003/10/29 15:02:47  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R1.33
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. #ifndef NCBIARGS__HPP
  10. #define NCBIARGS__HPP
  11. /*  $Id: ncbiargs.hpp,v 1000.0 2003/10/29 15:02:47 gouriano Exp $
  12.  * ===========================================================================
  13.  *
  14.  *                            PUBLIC DOMAIN NOTICE
  15.  *               National Center for Biotechnology Information
  16.  *
  17.  *  This software/database is a "United States Government Work" under the
  18.  *  terms of the United States Copyright Act.  It was written as part of
  19.  *  the author's official duties as a United States Government employee and
  20.  *  thus cannot be copyrighted.  This software/database is freely available
  21.  *  to the public for use. The National Library of Medicine and the U.S.
  22.  *  Government have not placed any restriction on its use or reproduction.
  23.  *
  24.  *  Although all reasonable efforts have been taken to ensure the accuracy
  25.  *  and reliability of the software and data, the NLM and the U.S.
  26.  *  Government do not and cannot warrant the performance or results that
  27.  *  may be obtained by using this software or data. The NLM and the U.S.
  28.  *  Government disclaim all warranties, express or implied, including
  29.  *  warranties of performance, merchantability or fitness for any particular
  30.  *  purpose.
  31.  *
  32.  *  Please cite the author in any work or product based on this material.
  33.  *
  34.  * ===========================================================================
  35.  *
  36.  * Author:  Denis Vakatov
  37.  *
  38.  *
  39.  */
  40. /// @file ncbiargs.hpp
  41. /// Defines command line argument related classes.
  42. ///
  43. /// The CArgDescriptions and CArgDesc classes are used for describing
  44. /// unparsed arguments; CArgs and CArgValue for parsed argument values;
  45. /// CArgException and CArgHelpException for argument exceptions; and CArgAllow, 
  46. /// CArgAllow_{Strings, ..., Integers, Doubles} for argument constraints.
  47. ///
  48. /// The following description is included as applies to several classes in
  49. /// this file:
  50. ///
  51. /// Parsing and validation of command-line arguments are done according to
  52. /// user-provided descriptions. The command line has the following syntax:
  53. ///
  54. /// Command string:
  55. ///
  56. ///    progname  {arg_key, arg_key_opt, arg_key_dflt, arg_flag} [--]
  57. ///              {arg_pos} {arg_pos_opt, arg_pos_dflt}
  58. ///              {arg_extra} {arg_extra_opt}
  59. ///
  60. /// where:
  61. ///
  62. ///   arg_key        :=  -<key> <value>    -- (mandatory)
  63. ///   arg_key_opt    := [-<key> <value>]   -- (optional, without default value)
  64. ///   arg_key_dflt   := [-<key> <value>]   -- (optional, with default value)
  65. ///   arg_flag       := -<flag>            -- (always optional)
  66. ///   "--" is an optional delimiter to indicate the beginning of pos. args
  67. ///   arg_pos        := <value>            -- (mandatory)
  68. ///   arg_pos_opt    := [<value>]          -- (optional, without default value)
  69. ///   arg_pos_dflt   := [<value>]          -- (optional, with default value)
  70. ///   arg_extra      := <value>            -- (dep. on the constraint policy)
  71. ///   arg_extra_opt  := [<value>]          -- (dep. on the constraint policy)
  72. ///
  73. /// and:
  74. ///
  75. ///   <key> must be followed by <value>
  76. ///   <flag> and <key> are case-sensitive, and they can contain
  77. ///                    only alphanumeric characters
  78. ///   <value> is an arbitrary string (additional constraints can
  79. ///           be applied in the argument description, see "EType")
  80. ///
  81. /// {arg_pos***} and {arg_extra***} -- position-dependent arguments, with
  82. /// no tag preceding them.
  83. /// {arg_pos***} -- have individual names and descriptions (see methods
  84. /// AddPositional***).
  85. /// {arg_extra***} have one description for all (see method AddExtra).
  86. /// User can apply constraints on the number of mandatory and optional
  87. /// {arg_extra***} arguments.
  88. #include <corelib/ncbistd.hpp>
  89. #include <corelib/ncbiobj.hpp>
  90. #include <corelib/ncbi_limits.h>
  91. #include <memory>
  92. #include <set>
  93. #include <list>
  94. #include <vector>
  95. /** @addtogroup Args
  96.  *
  97.  * @{
  98.  */
  99. BEGIN_NCBI_SCOPE
  100. // Some necessary forward declarations.
  101. class CNcbiArguments;
  102. class CArgAllow;
  103. /////////////////////////////////////////////////////////////////////////////
  104. ///
  105. /// CArgException --
  106. ///
  107. /// Define exceptions class for incorrectly formed arguments.
  108. ///
  109. /// CArgException inherits its basic functionality from CCoreException
  110. /// and defines additional error codes for malformed arguments.
  111. class NCBI_XNCBI_EXPORT CArgException : public CCoreException
  112. {
  113. public:
  114.     /// Error types for improperly formatted arguments.
  115.     ///
  116.     /// These error conditions are checked for and caught when processing
  117.     /// arguments.
  118.     enum EErrCode {
  119.         eInvalidArg,    ///< Invalid argument
  120.         eNoValue,       ///< Expecting an argument value
  121.         eWrongCast,     ///< Incorrect cast for an argument
  122.         eConvert,       ///< Conversion problem
  123.         eNoFile,        ///< Expecting a file
  124.         eConstraint,    ///< Argument value outside constraints
  125.         eArgType,       ///< Wrong argument type
  126.         eNoArg,         ///< No argument
  127.         eSynopsis       ///< Synopois error
  128.     };
  129.     /// Translate from the error code value to its string representation.
  130.     virtual const char* GetErrCodeString(void) const
  131.     {
  132.         switch (GetErrCode()) {
  133.         case eInvalidArg: return "eInvalidArg";
  134.         case eNoValue:    return "eNoValue";
  135.         case eWrongCast:  return "eWrongCast";
  136.         case eConvert:    return "eConvert";
  137.         case eNoFile:     return "eNoFile";
  138.         case eConstraint: return "eConstraint";
  139.         case eArgType:    return "eArgType";
  140.         case eNoArg:      return "eNoArg";
  141.         case eSynopsis:   return "eSynopsis";
  142.         default:    return CException::GetErrCodeString();
  143.         }
  144.     }
  145.     // Standard exception bolier plate code.
  146.     NCBI_EXCEPTION_DEFAULT(CArgException, CCoreException);
  147. };
  148. /////////////////////////////////////////////////////////////////////////////
  149. ///
  150. /// CArgHelpException --
  151. ///
  152. /// Define exception class that gets thrown for Help messages.
  153. ///
  154. /// CArgException inherits its basic functionality from CArgException
  155. /// and defines an additional error code for help.
  156. class NCBI_XNCBI_EXPORT CArgHelpException : public CArgException
  157. {
  158. public:
  159.     /// Error type for help exception.
  160.     enum EErrCode {
  161.         eHelp           ///< Error code for help message
  162.     };
  163.     /// Translate from the error code value to its string representation.
  164.     virtual const char* GetErrCodeString(void) const
  165.     {
  166.         switch (GetErrCode()) {
  167.         case eHelp: return "eHelp";
  168.         default:    return CException::GetErrCodeString();
  169.         }
  170.     }
  171.     // Standard exception bolier plate code.
  172.     NCBI_EXCEPTION_DEFAULT(CArgHelpException, CArgException);
  173. };
  174. /////////////////////////////////////////////////////////////////////////////
  175. ///
  176. /// CArgValue --
  177. ///
  178. /// Generic abstract base class for argument values.
  179. class NCBI_XNCBI_EXPORT CArgValue : public CObject
  180. {
  181. public:
  182.     /// Get argument name.
  183.     const string& GetName(void) const { return m_Name; }
  184.     /// Check if argument holds a value.
  185.     ///
  186.     /// Argument does not hold value if it was described as optional argument
  187.     /// without default value, and if it was not passed a value in the command
  188.     /// line.  On attempt to retrieve the value from such "no-value" argument,
  189.     /// exception will be thrown.
  190.     virtual bool HasValue(void) const = 0;
  191.     /// Operator () form of HasValue() method.
  192.     ///
  193.     /// @sa
  194.     ///   HasValue()
  195.     operator bool (void) const { return  HasValue(); }
  196.     /// Operator !() returns the value of !HasValue() method.
  197.     ///
  198.     /// @sa
  199.     ///   HasValue()
  200.     bool operator!(void) const { return !HasValue(); }
  201.     /// Get the argument's string value.
  202.     ///
  203.     /// If it is a value of a flag argument, then return either "true"
  204.     /// or "false".
  205.     /// @sa
  206.     ///   AsInteger(), AsDouble(), AsBoolean()
  207.     virtual const string& AsString(void) const = 0;
  208.     /// Get the argument's integer value.
  209.     ///
  210.     /// If you request a wrong value type, such as a call to "AsInteger()"
  211.     /// for a "boolean" argument, an exception is thrown.
  212.     /// @sa
  213.     ///   AsString(), AsDouble, AsBoolean()
  214.     virtual int    AsInteger(void) const = 0;
  215.     /// Get the argument's double value.
  216.     ///
  217.     /// If you request a wrong value type, such as a call to "AsDouble()"
  218.     /// for a "boolean" argument, an exception is thrown.
  219.     /// @sa
  220.     ///   AsString(), AsInteger, AsBoolean()
  221.     virtual double AsDouble (void) const = 0;
  222.     /// Get the argument's boolean value.
  223.     ///
  224.     /// If you request a wrong value type, such as a call to "AsBoolean()"
  225.     /// for a "integer" argument, an exception is thrown.
  226.     /// @sa
  227.     ///   AsString(), AsInteger, AsDouble()
  228.     virtual bool   AsBoolean(void) const = 0;
  229.     /// Get the argument as an input file stream.
  230.     virtual CNcbiIstream& AsInputFile (void) const = 0;
  231.     /// Get the argument as an output file stream.
  232.     virtual CNcbiOstream& AsOutputFile(void) const = 0;
  233.     /// Close the file.
  234.     virtual void CloseFile (void) const = 0;
  235. protected:
  236.     friend class CArgs;
  237.     /// Protected constructor and destructor.
  238.     ///
  239.     /// Prohibit explicit instantiation of CArgValue with name.
  240.     CArgValue(const string& name);
  241.     virtual ~CArgValue(void);
  242.     string m_Name;          ///< Argument name
  243. };
  244. /////////////////////////////////////////////////////////////////////////////
  245. ///
  246. /// CArgs --
  247. ///
  248. /// Defines parsed arguments.
  249. ///
  250. /// Argument values are obtained from the unprocessed command-line arguments
  251. /// (via CNcbiArguments) and then verified and processed according to the
  252. /// argument descriptions defined by user in "CArgDescriptions".
  253. ///
  254. /// NOTE:  the extra arguments can be accessed using virtual names:
  255. ///           "#1", "#2", "#3", ..., "#<GetNExtra()>"
  256. ///        in the order of insertion (by method Add).
  257. ///
  258. class NCBI_XNCBI_EXPORT CArgs
  259. {
  260. public:
  261.     /// Constructor.
  262.     CArgs(void);
  263.     /// Destructor.
  264.     ~CArgs(void);
  265.     /// Check existence of argument description.
  266.     ///
  267.     /// Return TRUE if arg "name" was described in the parent CArgDescriptions.
  268.     bool Exist(const string& name) const;
  269.     /// Get value of argument by name.
  270.     ///
  271.     /// Throw an exception if such argument does not exist.
  272.     /// @sa
  273.     ///   Exist() above.
  274.     const CArgValue& operator[] (const string& name) const;
  275.     /// Get the number of unnamed positional (a.k.a. extra) args.
  276.     size_t GetNExtra(void) const { return m_nExtra; }
  277.     /// Return N-th extra arg value,  N = 1 to GetNExtra().
  278.     const CArgValue& operator[] (size_t idx) const;
  279.     /// Print (append) all arguments to the string "str" and return "str".
  280.     string& Print(string& str) const;
  281.     /// Add new argument name and value.
  282.     ///
  283.     /// Throw an exception if the "name" is not an empty string, and if
  284.     /// there is an argument with this name already.
  285.     ///
  286.     /// HINT: Use empty "name" to add extra (unnamed) args, and they will be
  287.     /// automagically assigned with the virtual names: "#1", "#2", "#3", etc.
  288.     void Add(CArgValue* arg);
  289.     /// Check if there are no arguments in this container.
  290.     bool IsEmpty(void) const;
  291. private:
  292.     typedef set< CRef<CArgValue> >  TArgs;   ///< Type for arguments
  293.     typedef TArgs::iterator         TArgsI;  ///< Type for iterator
  294.     typedef TArgs::const_iterator   TArgsCI; ///< Type for const iterator
  295.     TArgs  m_Args;    ///< Assoc. map of arguments' name/value
  296.     size_t m_nExtra;  ///< Cached # of unnamed positional arguments 
  297.     /// Find argument value with name "name".
  298.     TArgsCI x_Find(const string& name) const;
  299. };
  300. class CArgDesc;
  301. /////////////////////////////////////////////////////////////////////////////
  302. ///
  303. /// CArgDescriptions --
  304. ///
  305. /// Description of unparsed arguments.
  306. ///
  307. /// Container to store the command-line argument descriptions. Provides the
  308. /// means for the parsing and verification of command-line arguments against
  309. /// the contained descriptions.
  310. ///
  311. /// Example: Translating "CNcbiArguments" ---> "CArgs".
  312. /// Can also be used to compose and print out the USAGE info.
  313. class NCBI_XNCBI_EXPORT CArgDescriptions
  314. {
  315. public:
  316.     /// Constructor.
  317.     ///
  318.     /// If "auto_help" is passed TRUE, then a special flag "-h" will be added
  319.     /// to the list of accepted arguments. Passing "-h" in the command line
  320.     /// will printout USAGE and ignore all other passed arguments.
  321.     CArgDescriptions(bool auto_help = true);
  322.     /// Destructor.
  323.     virtual ~CArgDescriptions(void);
  324.     /// Available argument types.
  325.     enum EType {
  326.         eString = 0, ///< An arbitrary string
  327.         eBoolean,    ///< {'true', 't', 'false', 'f'},  case-insensitive
  328.         eInteger,    ///< Convertible into an integer number (int)
  329.         eDouble,     ///< Convertible into a floating point number (double)
  330.         eInputFile,  ///< Name of file (must exist and be readable)
  331.         eOutputFile, ///< Name of file (must be writeable)
  332.         k_EType_Size ///< For internal use only
  333.     };
  334.     /// Get argument type's name string.
  335.     static const string& GetTypeName(EType type);
  336.     /// File related flags.
  337.     ///
  338.     /// Must match the argument type, or an exception will be thrown.
  339.     /// Used for eInputFile and eOutputFiler argument types.
  340.     enum EFlags {
  341.         fPreOpen = 0x1,  ///< Open file right away for eInputFile, eOutputFile
  342.         fBinary  = 0x2,  ///< Open as binary file for eInputFile, eOutputFile
  343.         fAppend  = 0x10  ///< Append to end-of-file for eOutputFile only
  344.     };
  345.     typedef unsigned int TFlags;  ///< Binary OR of "EFlags"
  346.     /// Add description for mandatory key.
  347.     ///
  348.     /// Mandatory key has the syntax:
  349.     ///
  350.     ///   arg_key := -<key> <value>
  351.     ///
  352.     /// Will throw exception CArgException if:
  353.     ///  - description with name "name" already exists
  354.     ///  - "name" contains symbols other than {alnum}
  355.     ///  - "synopsis" contains symbols other than {alnum, '_'}
  356.     ///  - "flags" are inconsistent with "type"
  357.     ///
  358.     /// Any argument can be later referenced using its unique name "name".
  359.     void AddKey(const string& name,       ///< Name of argument key
  360.                 const string& synopsis,   ///< Synopis for argument
  361.                 const string& comment,    ///< Argument description
  362.                 EType         type,       ///< Argument type
  363.                 TFlags        flags = 0   ///< Optional file related flags
  364.                );
  365.     /// Add description for optional key without default value.
  366.     ///
  367.     /// Optional key without default value has the following syntax:
  368.     ///
  369.     ///   arg_key_opt := [-<key> <value>]
  370.     ///
  371.     /// Will throw exception CArgException if:
  372.     ///  - description with name "name" already exists
  373.     ///  - "name" contains symbols other than {alnum}
  374.     ///  - "synopsis" contains symbols other than {alnum, '_'}
  375.     ///  - "flags" are inconsistent with "type"
  376.     ///
  377.     /// Any argument can be later referenced using its unique name "name".
  378.     void AddOptionalKey(const string& name,     ///< Name of argument key 
  379.                         const string& synopsis, ///< Synopis for argument
  380.                         const string& comment,  ///< Argument description
  381.                         EType         type,     ///< Argument type
  382.                         TFlags        flags = 0 ///< Optional file flags
  383.                        );
  384.     /// Add description for optional key with default value.
  385.     ///
  386.     /// Optional key with default value has the following syntax:
  387.     ///
  388.     ///   arg_key_dflt := [-<key> <value>]
  389.     ///
  390.     /// Will throw exception CArgException if:
  391.     ///  - description with name "name" already exists
  392.     ///  - "name" contains symbols other than {alnum}
  393.     ///  - "synopsis" contains symbols other than {alnum, '_'}
  394.     ///  - "flags" are inconsistent with "type"
  395.     ///
  396.     /// Any argument can be later referenced using its unique name "name".
  397.     void AddDefaultKey(const string& name,          ///< Name of argument key 
  398.                        const string& synopsis,      ///< Synopis for argument
  399.                        const string& comment,       ///< Argument description
  400.                        EType         type,          ///< Argument type
  401.                        const string& default_value, ///< Default value
  402.                        TFlags        flags = 0      ///< Optional file flags
  403.                       );
  404.     /// Add description for flag argument.
  405.     ///
  406.     /// Flag argument has the following syntax:
  407.     ///
  408.     ///  arg_flag  := -<flag>,     <flag> := "name"
  409.     ///
  410.     /// If argument "set_value" is TRUE, then:
  411.     ///    - if the flag is provided (in the command-line), then the resultant
  412.     ///      CArgValue::HasValue() will be TRUE;
  413.     ///    - else it will be FALSE.
  414.     ///
  415.     /// Setting argument "set_value" to FALSE will reverse the above meaning.
  416.     ///
  417.     /// NOTE: If CArgValue::HasValue() is TRUE, then AsBoolean() is
  418.     /// always TRUE.
  419.     void AddFlag(const string& name,            ///< Name of argument
  420.                  const string& comment,         ///< Argument description
  421.                  bool          set_value = true ///< Is value set or not?
  422.                 );
  423.     /// Add description for mandatory postional argument.
  424.     ///
  425.     /// Mandatory positional argument has the following syntax:
  426.     ///
  427.     ///   arg_pos := <value>
  428.     ///
  429.     /// NOTE: For all types of positional arguments:
  430.     /// - The order is important! That is, the N-th positional argument passed
  431.     ///   in the cmd.-line will be matched against (and processed according to)
  432.     ///   the N-th added named positional argument description.
  433.     /// - Mandatory positional args always go first.
  434.     ///
  435.     /// Will throw exception CArgException if:
  436.     ///  - description with name "name" already exists
  437.     ///  - "name" contains symbols other than {alnum}
  438.     ///  - "flags" are inconsistent with "type"
  439.     ///
  440.     /// Any argument can be later referenced using its unique name "name".
  441.     void AddPositional(const string& name,     ///< Name of argument
  442.                        const string& comment,  ///< Argument description
  443.                        EType         type,     ///< Argument type
  444.                        TFlags        flags = 0 ///< Optional file flags
  445.                       );
  446.     /// Add description for optional positional argument without default
  447.     /// value.
  448.     ///
  449.     /// Optional positional argument, without default value has the following
  450.     /// syntax:
  451.     ///
  452.     ///  arg_pos_opt := [<value>]
  453.     ///
  454.     /// Will throw exception CArgException if:
  455.     ///  - description with name "name" already exists
  456.     ///  - "name" contains symbols other than {alnum}
  457.     ///  - "flags" are inconsistent with "type"
  458.     ///
  459.     /// Any argument can be later referenced using its unique name "name".
  460.     /// @sa
  461.     ///   NOTE for AddPositional()
  462.     void AddOptionalPositional(const string& name,     ///< Name of argument
  463.                                const string& comment,  ///< Argument descr.
  464.                                EType         type,     ///< Argument type
  465.                                TFlags        flags = 0 ///< Optional file flgs
  466.                               );
  467.     /// Add description for optional positional argument with default value.
  468.     ///
  469.     /// Optional positional argument with default value has the following
  470.     /// syntax:
  471.     ///
  472.     ///  arg_pos_dflt := [<value>]
  473.     ///
  474.     /// Will throw exception CArgException if:
  475.     ///  - description with name "name" already exists
  476.     ///  - "name" contains symbols other than {alnum}
  477.     ///  - "flags" are inconsistent with "type"
  478.     ///
  479.     /// @sa
  480.     ///   NOTE for AddPositional()
  481.     void AddDefaultPositional(const string& name,   ///< Name of argument
  482.                               const string& comment,///< Argument description
  483.                               EType         type,   ///< Argument type
  484.                               const string& default_value, ///< Default value
  485.                               TFlags        flags = 0 ///< Optional file flags
  486.                              );
  487.     /// Add description for extra unnamed positional arguments.
  488.     ///
  489.     /// Provide description for the extra unnamed positional arguments.
  490.     /// By default, no extra args are allowed.
  491.     /// The name of this description is always an empty string.
  492.     /// Names of the resulting arg.values will be:  "#1", "#2", ...
  493.     ///
  494.     /// Will throw exception CArgException if:
  495.     ///  - description with name "name" already exists
  496.     ///  - "flags" are inconsistent with "type"
  497.     void AddExtra(unsigned      n_mandatory, ///< Number of mandatory args.
  498.                   unsigned      n_optional,  ///< Number of optional args.
  499.                   const string& comment,     ///< Argument description
  500.                   EType         type,        ///< Argument type
  501.                   TFlags        flags = 0    ///< Optional file flags
  502.                  );
  503.     /// Set additional user defined constraint on argument value.
  504.     ///
  505.     /// Constraint is defined by CArgAllow and its derived classes.
  506.     /// The constraint object must be allocated by "new", and it must NOT be
  507.     /// freed by "delete" after it has been passed to CArgDescriptions!
  508.     /// @sa
  509.     ///   See "CArgAllow_***" classes for some pre-defined constraints
  510.     void SetConstraint(const string& name, CArgAllow* constraint);
  511.     /// Check if there is already an argument description with specified name.
  512.     bool Exist(const string& name) const;
  513.     /// Delete description with name "name".
  514.     ///
  515.     /// Throw the CArgException (eSynposis error code) exception if the
  516.     /// specified name cannot be found.
  517.     void Delete(const string& name);
  518.     /// Set extra info to be used by PrintUsage().
  519.     void SetUsageContext(const string& usage_name,           ///< Program name  
  520.                          const string& usage_description,    ///< Usage descr.
  521.                          bool          usage_sort_args = false,///< Sort args.
  522.                          SIZE_TYPE     usage_width = 78);    ///< Format width
  523.     /// Print usage and exit.
  524.     ///
  525.     /// Force to print USAGE unconditionally (and then exit) if no
  526.     /// command-line args are present.
  527.     void PrintUsageIfNoArgs(bool do_print = true);
  528.     /// Print usage message to end of specified string.
  529.     ///
  530.     /// Printout USAGE and append to the string "str" using  provided
  531.     /// argument descriptions and usage context.
  532.     /// @return
  533.     ///   Appended "str"
  534.     virtual string& PrintUsage(string& str) const;
  535.     /// Verify if argument "name" is spelled correctly.
  536.     ///
  537.     /// Argument name can contain only  alphanumeric characters and
  538.     /// underscore ('_'), or be empty.
  539.     static bool VerifyName(const string& name, bool extended = false);
  540. private:
  541.     typedef set< AutoPtr<CArgDesc> >  TArgs;    ///< Argument descr. type
  542.     typedef TArgs::iterator           TArgsI;   ///< Arguments iterator
  543.     typedef TArgs::const_iterator     TArgsCI;  ///< Const arguments iterator
  544.     typedef /*deque*/vector<string>   TPosArgs; ///< Positional arg. vector
  545.     typedef list<string>              TKeyFlagArgs; ///< List of flag arguments
  546.     TArgs        m_Args;      ///< Assoc.map of arguments' name/descr
  547.     TPosArgs     m_PosArgs;   ///< Pos. args, ordered by position in cmd.-line
  548.     TKeyFlagArgs m_KeyFlagArgs; ///< Key/flag args, in order of insertion
  549.     unsigned     m_nExtra;    ///> # of mandatory extra args
  550.     unsigned     m_nExtraOpt; ///< # of optional  extra args
  551.     // Extra USAGE info
  552.     string    m_UsageName;         ///< Program name
  553.     string    m_UsageDescription;  ///< Program description
  554.     bool      m_UsageSortArgs;     ///< Sort alphabetically on usage printout
  555.     SIZE_TYPE m_UsageWidth;        ///< Maximum length of a usage line
  556.     bool      m_AutoHelp;          ///< Special flag "-h" activated
  557.     bool      m_UsageIfNoArgs;     ///< Print usage and exit if no args passed
  558.     // Internal methods
  559.     /// Helper method to find named parameter.
  560.     TArgsI  x_Find(const string& name);
  561.     /// Helper method to find named parameter -- const version.
  562.     TArgsCI x_Find(const string& name) const;
  563.     // Helper method for adding description.
  564.     void x_AddDesc(CArgDesc& arg); 
  565.     /// Helper method for doing pre-processing consistency checks.
  566.     void x_PreCheck(void) const; 
  567.     /// Helper method for checking if auto help requested and throw
  568.     /// CArgHelpException if help requested.
  569.     void x_CheckAutoHelp(const string& arg) const;
  570.     /// Process arguments.
  571.     ///
  572.     /// Helper method to process arguments and build a CArgs object that is
  573.     /// passed as the args parameter.
  574.     /// @return
  575.     ///   TRUE if specified "arg2" was used.
  576.     bool    x_CreateArg(const string& arg1, ///< Argument to process 
  577.                         bool have_arg2, ///< Is there an arg. that follows?
  578.                         const string& arg2, ///< Following argument
  579.                         unsigned* n_plain,  ///< Indicates number of args 
  580.                         CArgs& args         ///< Contains processed args
  581.                        ) const;
  582.     /// Helper method for doing post-processing consistency checks.
  583.     void    x_PostCheck(CArgs& args, unsigned n_plain) const;
  584. public:
  585.     /// Create parsed arguments in CArgs object.
  586.     ///
  587.     /// Parse command-line arguments, and create "CArgs" args object 
  588.     /// from the passed command-line arguments "argc" and "argv".
  589.     ///
  590.     /// Throw 
  591.     ///  - CArgException on error
  592.     ///  - CArgHelpException if USAGE printout was requested ("-h" flag)
  593.     ///
  594.     /// NOTE: You can deallocate the resulting "CArgs" object using 'delete'.
  595.     ///
  596.     /// Examples:
  597.     ///
  598.     /// (1) int main(int argc, const char* argv[]) {
  599.     ///         CreateArgs(desc, argc, argv);
  600.     ///     }
  601.     ///
  602.     /// (2) CNcbiArguments ncbi_args;
  603.     ///     CreateArgs(desc, ncbi_args.Size(), ncbi_args);
  604.     template<class TSize, class TArray>
  605.     CArgs* CreateArgs(TSize argc, TArray argv) const
  606.     {
  607.         // Pre-processing consistency checks
  608.         x_PreCheck();
  609.         // Check for "-h" flag
  610.         if ( m_AutoHelp ) {
  611.             for (TSize i = 1;  i < argc;  i++) {
  612.                 x_CheckAutoHelp(argv[i]);
  613.             }
  614.         }
  615.         // Create new "CArgs" to fill up, and parse cmd.-line args into it
  616.         auto_ptr<CArgs> args(new CArgs());
  617.         unsigned int n_plain = kMax_UInt;
  618.         for (TSize i = 1;  i < argc;  i++) {
  619.             bool have_arg2 = (i + 1 < argc);
  620.             if ( x_CreateArg(argv[i], have_arg2,
  621.                              have_arg2 ? (string) argv[i+1] : kEmptyStr,
  622.                              &n_plain, *args) )
  623.                 i++;
  624.         }
  625.         // Check if there were any arguments at all
  626.         if (n_plain == kMax_UInt) {
  627.             n_plain = 0;
  628.         }
  629.         // Post-processing consistency checks
  630.         x_PostCheck(*args, n_plain);
  631.         return args.release();
  632.     }
  633.     CArgs* CreateArgs(const CNcbiArguments& argv) const;
  634. };
  635. /////////////////////////////////////////////////////////////////////////////
  636. ///
  637. /// CArgAllow --
  638. ///
  639. /// Abstract base class for defining argument constraints.
  640. ///
  641. /// Other user defined constraints are defined by deriving from this abstract
  642. /// base class:
  643. ///
  644. ///  - CArgAllow_Symbols  -- symbol from a set of allowed symbols
  645. ///  - CArgAllow_String   -- string to contain only allowed symbols 
  646. ///  - CArgAllow_Strings  -- string from a set of allowed strings
  647. ///  - CArgAllow_Integers -- integer value to fall within a given interval
  648. ///  - CArgAllow_Doubles  -- floating-point value to fall in a given interval
  649. class NCBI_XNCBI_EXPORT CArgAllow : public CObject
  650. {
  651. public:
  652.     /// Verify if specified value is allowed.
  653.     virtual bool Verify(const string &value) const = 0;
  654.     /// Get usage information.
  655.     virtual string GetUsage(void) const = 0;
  656. protected:
  657.     /// Protected destructor.
  658.     ///
  659.     /// Prohibit from the allocation on stack or in the static data segment,
  660.     /// and from the explicit deallocation by "delete".
  661.     virtual ~CArgAllow(void);
  662. };
  663. /////////////////////////////////////////////////////////////////////////////
  664. ///
  665. /// CArgAllow_Symbols --
  666. ///
  667. /// Define constraint to describe exactly one symbol.
  668. ///
  669. /// Argument to be exactly one symbol from the specified set of symbols.
  670. ///
  671. /// Examples:
  672. /// - To allow only symbols 'a', 'b' and 'Z' for argument "MyArg":
  673. ///   SetConstraint("MyArg", new CArgAllow_Symbols("abZ"))
  674. /// - To allow only printable symbols (according to "isprint()" from <ctype.h>):
  675. ///   SetConstraint("MyArg", new CArgAllow_Symbols(CArgAllow_Symbols::ePrint))
  676. class NCBI_XNCBI_EXPORT CArgAllow_Symbols : public CArgAllow
  677. {
  678. public:
  679.     /// Symbol class for defining sets of characters.
  680.     ///
  681.     /// Symbol character classes patterned after those defined in <ctype.h>.
  682.     enum ESymbolClass {
  683.         // Standard character class from <ctype.h>:  isalpha(), isdigit(), etc.
  684.         eAlnum,  ///< Alphanumeric characters
  685.         eAlpha,  ///< Alphabet characters
  686.         eCntrl,  ///< Control characters
  687.         eDigit,  ///< Digit characters
  688.         eGraph,  ///< Graphical characters
  689.         eLower,  ///< Lowercase characters
  690.         ePrint,  ///< Printable characters
  691.         ePunct,  ///< Punctuation characters
  692.         eSpace,  ///< Space characters
  693.         eUpper,  ///< Uppercase characters
  694.         eXdigit, ///< Hexadecimal characters
  695.         eUser    ///< User defined characters using constructor with string&
  696.     };
  697.     /// Constructor.
  698.     CArgAllow_Symbols(ESymbolClass symbol_class);
  699.     /// Constructor for user defined eUser class.
  700.     CArgAllow_Symbols(const string& symbol_set);
  701. protected:
  702.     /// Verify if specified value is allowed.
  703.     virtual bool Verify(const string& value) const;
  704.     /// Get usage information.
  705.     virtual string GetUsage(void) const;
  706.     /// Protected destructor.
  707.     virtual ~CArgAllow_Symbols(void);
  708.     ESymbolClass m_SymbolClass; ///< Symbol class for constraint
  709.     string       m_SymbolSet;   ///< Use if  m_SymbolClass == eUser
  710. };
  711. /////////////////////////////////////////////////////////////////////////////
  712. ///
  713. /// CArgAllow_String --
  714. ///
  715. /// Define constraint to describe string argument.
  716. ///
  717. /// Argument to be a string containing only allowed symbols.
  718. ///
  719. /// Examples:
  720. /// - To allow string containing only symbols 'a', 'b' and 'Z' for arg MyArg:
  721. ///   SetConstraint("MyArg", new CArgAllow_String("abZ"))
  722. /// - To allow only numeric symbols (according to "isdigit()" from <ctype.h>):
  723. ///   SetConstraint("MyArg", new CArgAllow_String(CArgAllow_String::eDigit))
  724. class NCBI_XNCBI_EXPORT CArgAllow_String : public CArgAllow_Symbols
  725. {
  726. public:
  727.     /// Constructor.
  728.     CArgAllow_String(ESymbolClass symbol_class);
  729.     /// Constructor for user defined eUser class.
  730.     CArgAllow_String(const string& symbol_set);
  731. protected:
  732.     /// Verify if specified value is allowed.
  733.     virtual bool Verify(const string& value) const;
  734.     /// Get usage information.
  735.     virtual string GetUsage(void) const;
  736. };
  737. /////////////////////////////////////////////////////////////////////////////
  738. ///
  739. /// CArgAllow_Strings --
  740. ///
  741. /// Define constraint to describe set of string values.
  742. ///
  743. /// Argument to have only particular string values. Use the Allow() method to
  744. /// add the allowed string values, which can be daisy-chained.
  745. ///
  746. /// Examples:
  747. /// - SetConstraint("a", (new CArgAllow_Strings)->
  748. ///                  Allow("foo")->Allow("bar")->Allow("etc"))
  749. /// - You can use "operator,()" to shorten the notation:
  750. ///   SetConstraint("b", &(*new CArgAllow_Strings, "foo", "bar", "etc"))
  751. class NCBI_XNCBI_EXPORT CArgAllow_Strings : public CArgAllow
  752. {
  753. public:
  754.     /// Constructor.
  755.     CArgAllow_Strings(void);
  756.     /// Add allowed string values.
  757.     CArgAllow_Strings* Allow(const string& value);
  758.     /// Short notation operator for adding allowed string values.
  759.     /// @sa
  760.     ///   Allow()
  761.     CArgAllow_Strings& operator,(const string& value) { return *Allow(value); }
  762. protected:
  763.     /// Verify if specified value is allowed.
  764.     virtual bool   Verify(const string& value) const;
  765.     /// Get usage information.
  766.     virtual string GetUsage(void) const;
  767.     /// Protected destructor.
  768.     virtual ~CArgAllow_Strings(void);
  769. private:
  770.     set<string> m_Strings;  ///< Set of allowed string values
  771. };
  772. /////////////////////////////////////////////////////////////////////////////
  773. ///
  774. /// CArgAllow_Integers --
  775. ///
  776. /// Define constraint to describe range of integer values.
  777. ///
  778. /// Argument to have only integer values falling within given interval.
  779. ///
  780. /// Example:
  781. /// - SetConstraint("a2", new CArgAllow_Integers(-3, 34))
  782. class NCBI_XNCBI_EXPORT CArgAllow_Integers : public CArgAllow
  783. {
  784. public:
  785.     /// Constructor specifying range of allowed integer values.
  786.     CArgAllow_Integers(int x_min, int x_max);
  787. protected:
  788.     /// Verify if specified value is allowed.
  789.     virtual bool   Verify(const string& value) const;
  790.     /// Get usage information.
  791.     virtual string GetUsage(void) const;
  792. private:
  793.     int m_Min;  ///< Minimum value of range
  794.     int m_Max;  ///< Maximum value of range 
  795. };
  796. /////////////////////////////////////////////////////////////////////////////
  797. ///
  798. /// CArgAllow_Doubles --
  799. ///
  800. /// Define constraint to describe range of double values.
  801. ///
  802. /// Argument to have only double values falling within given interval.
  803. ///
  804. /// Example:
  805. /// - SetConstraint("a2", new CArgAllow_Doubles(0.01, 0.99))
  806. class NCBI_XNCBI_EXPORT CArgAllow_Doubles : public CArgAllow
  807. {
  808. public:
  809.     /// Constructor specifying range of allowed double values.
  810.     CArgAllow_Doubles(double x_min, double x_max);
  811. protected:
  812.     /// Verify if specified value is allowed.
  813.     virtual bool   Verify(const string& value) const;
  814.     /// Get usage information.
  815.     virtual string GetUsage(void) const;
  816. private:
  817.     double m_Min;   ///< Minimum value of range
  818.     double m_Max;   ///< Maximum value of range 
  819. };
  820. /////////////////////////////////////////////////////////////////////////////
  821. ///
  822. /// CArgDesc --
  823. ///
  824. /// Base class for the description of various types of argument.
  825. ///
  826. /// This was a pre-declaration; in MSVC, a predeclaration here causes a heap
  827. /// corruption on termination because this class's virtual destructor isn't
  828. /// defined at the moment the compiler instantiates the destructor of
  829. /// AutoPtr<CArgDesc>.
  830. class CArgDesc
  831. {
  832. public:
  833.     /// Constructor.
  834.     CArgDesc(const string& name,    ///< Argument name
  835.              const string& comment  ///< Argument description
  836.             );
  837.     /// Destructor.
  838.     virtual ~CArgDesc(void);
  839.     /// Get argument name.
  840.     const string& GetName   (void) const { return m_Name; }
  841.     /// Get arument description.
  842.     const string& GetComment(void) const { return m_Comment; }
  843.     /// Get usage synopis.
  844.     virtual string GetUsageSynopsis(bool name_only = false) const = 0;
  845.     /// Get usage comment attribute.
  846.     virtual string GetUsageCommentAttr(void) const = 0;
  847.     /// Process argument with specified value.
  848.     virtual CArgValue* ProcessArgument(const string& value) const = 0;
  849.     /// Process argument default.
  850.     virtual CArgValue* ProcessDefault(void) const = 0;
  851.     /// Verify argument default value.
  852.     virtual void VerifyDefault (void) const;
  853.     /// Set argument constraint.
  854.     virtual void SetConstraint(CArgAllow* constraint);
  855.     /// Get argument constraint.
  856.     virtual const CArgAllow* GetConstraint(void) const;
  857.     /// Get usage constraint.
  858.     string GetUsageConstraint(void) const;
  859. private:
  860.     string m_Name;      ///< Argument name
  861.     string m_Comment;   ///< Argument description
  862. };
  863. END_NCBI_SCOPE
  864. /* @} */
  865. /*
  866.  * ===========================================================================
  867.  * $Log: ncbiargs.hpp,v $
  868.  * Revision 1000.0  2003/10/29 15:02:47  gouriano
  869.  * PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R1.33
  870.  *
  871.  * Revision 1.33  2003/07/30 16:14:01  siyan
  872.  * Added explicit documentation for operators () and !()
  873.  *
  874.  * Revision 1.32  2003/07/24 11:48:02  siyan
  875.  * Made @sa text indentation consistent.
  876.  *
  877.  * Revision 1.31  2003/07/10 14:59:09  siyan
  878.  * Documentation changes.
  879.  *
  880.  * Revision 1.30  2003/05/28 18:00:11  kuznets
  881.  * CArgDescription::PrintUsage declared virtual to enable custom help screens
  882.  *
  883.  * Revision 1.29  2003/05/16 16:00:39  vakatov
  884.  * + CArgs::IsEmpty()
  885.  * + CArgDescriptions::PrintUsageIfNoArgs()
  886.  *
  887.  * Revision 1.28  2003/03/31 13:36:39  siyan
  888.  * Added doxygen support
  889.  *
  890.  * Revision 1.27  2003/02/10 18:06:15  kuznets
  891.  * Fixed problem with mandatory extra args
  892.  *
  893.  * Revision 1.26  2002/12/26 12:51:41  dicuccio
  894.  * Fixed some minor niggling errors with export specifiers in the wrong places.
  895.  *
  896.  * Revision 1.25  2002/12/18 22:53:21  dicuccio
  897.  * Added export specifier for building DLLs in windows.  Added global list of
  898.  * all such specifiers in mswin_exports.hpp, included through ncbistl.hpp
  899.  *
  900.  * Revision 1.24  2002/07/15 18:17:50  gouriano
  901.  * renamed CNcbiException and its descendents
  902.  *
  903.  * Revision 1.23  2002/07/11 14:17:53  gouriano
  904.  * exceptions replaced by CNcbiException-type ones
  905.  *
  906.  * Revision 1.22  2002/04/24 04:02:43  vakatov
  907.  * Do not use #NO_INCLASS_TMPL anymore -- apparently all modern
  908.  * compilers seem to be supporting in-class template methods.
  909.  *
  910.  * Revision 1.21  2002/04/11 20:39:16  ivanov
  911.  * CVS log moved to end of the file
  912.  *
  913.  * Revision 1.20  2001/05/17 14:50:34  lavr
  914.  * Typos corrected
  915.  *
  916.  * Revision 1.19  2001/03/16 16:39:13  vakatov
  917.  * + <corelib/ncbi_limits.h>
  918.  *
  919.  * Revision 1.18  2001/01/22 23:07:12  vakatov
  920.  * CArgValue::AsInteger() to return "int" (rather than "long")
  921.  *
  922.  * Revision 1.17  2000/12/24 00:12:59  vakatov
  923.  * Radically revamped NCBIARGS.
  924.  * Introduced optional key and posit. args without default value.
  925.  * Added new arg.value constraint classes.
  926.  * Passed flags to be detected by HasValue() rather than AsBoolean.
  927.  * Simplified constraints on the number of mandatory and optional extra args.
  928.  * Improved USAGE info and diagnostic messages. Etc...
  929.  *
  930.  * Revision 1.15  2000/11/29 00:07:25  vakatov
  931.  * Flag and key args not to be sorted in alphabetical order by default; see
  932.  * "usage_sort_args" in SetUsageContext().
  933.  *
  934.  * Revision 1.14  2000/11/24 23:28:31  vakatov
  935.  * CArgValue::  added CloseFile()
  936.  * CArgValue::  get rid of "change_mode" feature in AsInput/OutputFile()
  937.  *
  938.  * Revision 1.13  2000/11/22 22:04:29  vakatov
  939.  * Added special flag "-h" and special exception CArgHelpException to
  940.  * force USAGE printout in a standard manner
  941.  *
  942.  * Revision 1.12  2000/11/17 22:04:28  vakatov
  943.  * CArgDescriptions::  Switch the order of optional args in methods
  944.  * AddOptionalKey() and AddPlain(). Also, enforce the default value to
  945.  * match arg. description (and constraints, if any) at all times.
  946.  *
  947.  * Revision 1.11  2000/11/13 20:31:05  vakatov
  948.  * Wrote new test, fixed multiple bugs, ugly "features", and the USAGE.
  949.  *
  950.  * Revision 1.10  2000/10/20 22:23:26  vakatov
  951.  * CArgAllow_Strings customization;  MSVC++ fixes;  better diagnostic messages
  952.  *
  953.  * Revision 1.9  2000/10/20 20:25:53  vakatov
  954.  * Redesigned/reimplemented the user-defined arg.value constraints
  955.  * mechanism (CArgAllow-related classes and methods). +Generic clean-up.
  956.  *
  957.  * Revision 1.8  2000/10/06 21:57:51  butanaev
  958.  * Added Allow() function. Added classes CArgAllowValue, CArgAllowIntInterval.
  959.  *
  960.  * Revision 1.7  2000/09/29 17:11:22  butanaev
  961.  * Got rid of IsDefaultValue(), added IsProvided().
  962.  *
  963.  * Revision 1.6  2000/09/28 21:01:58  butanaev
  964.  * fPreOpen with opposite meaning took over fDelayOpen.
  965.  * IsDefaultValue() added which returns true if no
  966.  * value for an optional argument was provided in cmd. line.
  967.  *
  968.  * Revision 1.5  2000/09/22 21:27:13  butanaev
  969.  * Fixed buf in handling default arg values.
  970.  *
  971.  * Revision 1.4  2000/09/19 21:18:11  butanaev
  972.  * Added possibility to change file open mode on the fly
  973.  *
  974.  * Revision 1.3  2000/09/18 19:38:59  vasilche
  975.  * Added CreateArgs() from CNcbiArguments.
  976.  *
  977.  * Revision 1.2  2000/09/06 18:56:56  butanaev
  978.  * Added stdin, stdout support. Fixed bug in PrintOut.
  979.  *
  980.  * Revision 1.1  2000/08/31 23:54:47  vakatov
  981.  * Initial revision
  982.  *
  983.  * ===========================================================================
  984.  */
  985. #endif  /* NCBIARGS__HPP */