00001 /// \file CATCmdLine.h 00002 /// \brief Utility class for command-line parsing 00003 /// \ingroup CAT 00004 /// 00005 /// Copyright (c) 2007-2008 by Michael Ellison. 00006 /// See COPYING.txt for the \ref gaslicense License (MIT License). 00007 /// 00008 // $Author: mikeellison $ 00009 // $Date: 2008-01-12 11:38:12 -0600 (Sat, 12 Jan 2008) $ 00010 // $Revision: $ 00011 // $NoKeywords: $ 00012 00013 #ifndef _CATCmdLine_H_ 00014 #define _CATCmdLine_H_ 00015 00016 #include "CATInternal.h" 00017 #include "CATStringTable.h" 00018 00019 class CATCmdLine; 00020 00021 /// Callback prototype for command line arguments. 00022 /// 00023 /// \param cmdLinePtr Ptr to calling command line object 00024 /// \param userParam User defined param (this-> or similar context) 00025 /// \return CATResult If a callback returns an error, other callbacks 00026 /// will not be called. 00027 typedef CATResult (*CATCMDFUNC)(CATCmdLine* cmdLinePtr, 00028 void* userParam); 00029 00030 /// CATCMDLINEARG is the entry format used for the table that must be created 00031 /// and passed to CATCmdLine::Initialize to enable it to parse a command line. 00032 /// 00033 /// Each command entry is one of the following: 00034 /// -# Operand - A command with no switch preceeding it. 00035 /// -# Switch - A command that starts with a '/' or '-' and is proceeded by 00036 /// a single character. Multiple switches may follow a single 00037 /// '/' or '-' on the command line. 00038 /// -# Switch w/Arg - A switch, like the above, but with an argument after it. 00039 /// The switch and argument must be seperated by a space. 00040 /// 00041 /// Tables should begin with an operand for the executable itself, and end 00042 /// with an entry where CmdSwitch is -1. 00043 /// 00044 /// Operands MUST have the following: 00045 /// -# CmdSwitch must be 0 00046 /// -# TakesArg must be false. 00047 /// -# ArgOptDescId must be a short (single word) description of the operand. 00048 /// 00049 /// If a switch takes and argument, ArgOptDescId should be valid. Otherwise it should 00050 /// be 0. 00051 /// 00052 /// CmdGroup specifies a group of entries that are mutually exclusive. 00053 /// A CmdGroup of 0 indicates that the command is *not* part of a group. 00054 /// Any entries sharing the same CmdGroup value are in the same group. 00055 /// 00056 /// Entries and CmdGroup IDs should be in order. 00057 /// 00058 /// If a CmdGroup is required, set the Required flag on all entries. Otherwise, 00059 /// do not set the flag on *any* entries. 00060 /// 00061 struct CATCMDLINEARG 00062 { 00063 CATWChar CmdSwitch; ///< 0 indicates operand, -1 indicates end of table. 00064 CATInt32 CmdGroup; ///< Specifies mutually exclusive cmd group. 00065 CATBool Required; ///< If true, the argument is required. 00066 CATBool TakesArg; ///< must be false for operands, otherwise true if switch takes arg 00067 CATCMDFUNC Callback; ///< optional callback function 00068 CATUInt32 SwitchFlag; ///< optional flag to set for argument, \see CATCmdLine::GetSwitchFlags() 00069 CATResult ArgOptDescId; ///< ID of string for argument/operand description 00070 CATResult DescriptionId; ///< ID of string for verbose description of operand/argument 00071 }; 00072 00073 /// \class CATCmdArg 00074 /// \brief Helper class for \ref CATCmdLine to hold individual parsed command line 00075 /// arguments and switches. 00076 /// \ingroup CAT 00077 class CATCmdArg 00078 { 00079 public: 00080 /// Constructor for CATCmdArg. 00081 /// \param cmdSwitch Parsed switch value. 00082 CATCmdArg (CATWChar cmdSwitch); 00083 ~CATCmdArg ( ); 00084 00085 /// Sets the argument string value. 00086 /// \param argument The parsed argument string for the switch. 00087 void SetArg ( const CATWChar* argument ); 00088 00089 /// Retrieves the argument string value, if any. 00090 /// \return const CATWChar* String value of argument, or 0 if none. 00091 const CATWChar* GetArg (); 00092 00093 /// Retrieves the switch character for the argument. 00094 /// \return CATWChar switch character. 00095 CATWChar GetSwitch (); 00096 00097 protected: 00098 CATWChar fSwitch; ///< Parsed switch 00099 CATWChar* fArg; ///< Argument for switch, if any. 0 if not. 00100 }; 00101 00102 /// \class CATCmdLine 00103 /// \brief Generic command line parser 00104 /// \ingroup CAT 00105 /// 00106 /// CATCmdLine takes the command line (in argc/argvw format - using Wide Characters!) 00107 /// and parses it out into switches, arguments, and operands based on the passed-in table. 00108 /// 00109 /// You can query it after parsing, or just set it up to call your callback functions 00110 /// during the parse. 00111 /// 00112 /// To use: 00113 /// -# First call Initialize(), passing the table and app information in. 00114 /// -# Call Parse() with the command information to parse. 00115 /// -# Check the return value from Parse(). If all is good, it will be 0. 00116 /// -# Query the parsed data if desired. 00117 /// -# Optionally, call RunParsedCallbacks() to execute any callbacks 00118 /// for commands received on the command line. If a callback returns an 00119 /// error, no other callbacks will be called and RunParsedCallbacks() will 00120 /// return that error. 00121 /// -# You may go back to step 1 or 2 if desired to parse additional command lines. 00122 /// -# Call Uninitialize 00123 /// (optional - will be called on initialized objects during destructor) 00124 /// 00125 /// See \CATCMDLINEARG for the format of the table. 00126 class CATCmdLine 00127 { 00128 public: 00129 CATCmdLine ( ); 00130 virtual ~CATCmdLine ( ); 00131 00132 /// \brief Initialize the command parser. 00133 /// 00134 /// \param prefaceId Preface string to print at start of usage. 00135 /// \param cmdTable Application's command line parsing table. 00136 /// This may be built on the fly and deleted after 00137 /// initialization if desired. 00138 /// \param stringTable Application's string table. This is expected to 00139 /// be around for the lifetime of the command parser object. 00140 /// \param languageId Current language Id to use 00141 /// \return CATResult CAT_SUCCESS on success. 00142 CATResult Initialize ( CATResult prefaceId, 00143 const CATCMDLINEARG* cmdTable, 00144 CATStringTable* stringTable, 00145 CATLangId languageId = CATLANG_EN); 00146 00147 /// Uninitializes the command parser. 00148 /// This may be done manually, or will be called on destruction if needed. 00149 void Uninitialize( ); 00150 00151 /// \brief Parse a command line. 00152 /// Parsed data will overwrite previously parsed information. 00153 /// 00154 /// \param argc Number of arguments on command line 00155 /// \param argvw Command line in array form. 00156 /// 00157 /// \todo 00158 /// Need to add verification of results to Parsing 00159 CATResult Parse ( CATInt32 argc, 00160 CATWChar** argvw); 00161 00162 /// \brief Execute any callbacks specified by the table on 00163 /// the most recently parsed data. 00164 /// 00165 /// You *must* call Parse() prior to using this function! 00166 /// 00167 /// \param cbParam Parameter to be sent on function callbacks, if any. 00168 /// \return CATResult CAT_SUCCESS on success. 00169 CATResult RunParsedCallbacks(void* cbParam = 0); 00170 00171 /// \brief Prints the usage information for the app based on the table 00172 /// provided during initialization. 00173 /// \param maxColumns Max columns to print (e.g. screen width) 00174 CATResult PrintUsage ( CATInt32 maxColumns = 80); 00175 00176 /// \brief Returns true if the switch was present on the command line 00177 /// 00178 /// \param cmdSwitch Character switch to check 00179 /// \return CATBool true if set on cmd line, false otherwise. 00180 CATBool IsSwitchSet ( CATWChar cmdSwitch); 00181 00182 /// \brief Returns the argument (if any) for the switch specified on 00183 /// the command line. 00184 /// 00185 /// \param cmdSwitch Character switch to check 00186 /// \return const CATWChar* Ptr to argument or 0 if none. 00187 const CATWChar* GetArgument ( CATWChar cmdSwitch); 00188 00189 /// \brief Returns the argument (if any) for the switch specified on 00190 /// the command line after converting to an unsigned integer. 00191 /// 00192 /// Note: will accept hex or octal, per wcstoul. 00193 /// 00194 /// \param cmdSwitch Character switch to check 00195 /// \return CATUInt32 Unsigned integer argument. 0 if not found. 00196 CATUInt32 GetArgUInt ( CATWChar cmdSwitch); 00197 00198 /// \brief Returns the argument (if any) for the switch specified on 00199 /// the command line after converting to a signed integer. 00200 /// 00201 /// Note: will accept hex or octal, per wcstol. 00202 /// 00203 /// \param cmdSwitch Character switch to check 00204 /// \return CATInt32 Signed integer argument. 0 if not found. 00205 CATInt32 GetArgInt ( CATWChar cmdSwitch); 00206 00207 /// \brief Retrieves the number of operands received on the command line. 00208 /// 00209 /// \return CATUInt32 Number of operands (unswitched commands) 00210 CATUInt32 GetNumOps ( ); 00211 00212 /// \brief Retrieves an operand's string value by index 00213 /// 00214 /// \param index Operand index 00215 /// \return const CATWChar* Operand value from command line 00216 const CATWChar* GetOpByIndex ( CATUInt32 index); 00217 00218 00219 /// \brief Retrieves an operand's string value by it's DescriptionId 00220 /// in the command table. 00221 /// 00222 /// \param descId DescriptionId from command table 00223 /// \return const CATWChar* Operand value from command line 00224 const CATWChar* GetOpByDescId( CATResult descId); 00225 00226 /// \brief Retrieves the flags set by switches/operands that 00227 /// are present. 00228 /// 00229 /// Values of flags are set in the table in SwitchFlag. 00230 /// 00231 /// \return CATUInt32 All switch flags from command line OR'd together. 00232 CATUInt32 GetSwitchFlags(); 00233 protected: 00234 /// \brief Internal function to get the printed length of a command 00235 /// while printing usage information. 00236 /// 00237 /// \param index Command index in table 00238 /// \return CATInt32 Length of text to print command 00239 /// \sa PrintUsage() 00240 CATInt32 GetCmdLength ( CATUInt32 index); 00241 00242 /// \brief Internal function to print a command from the command table. 00243 /// 00244 /// \param index Command index in table 00245 /// \return CATInt32 Length of text to print command 00246 /// \sa PrintUsage() 00247 CATInt32 PrintCmdEntry( CATUInt32 index); 00248 00249 /// \brief Internal function to determine if a command is in a 00250 /// mutually exclusive command group, and if so - if it 00251 /// is the first or last in the group. 00252 /// 00253 /// \param index Index of the command 00254 /// \param isFirst Set to true on return if it is the first 00255 /// command in a group with > 1 members. 00256 /// \param isLast Set to true on return if it is the last 00257 /// command in a group with > 1 members. 00258 /// \return CATBool Returns true if it is in a group with > 1 members. 00259 CATBool IsCmdInGroup ( CATUInt32 index, 00260 CATBool& isFirst, 00261 CATBool& isLast); 00262 protected: 00263 CATUInt32 fSwitchFlags; ///< OR'd combination of all switch flags found during parse 00264 CATBool fInitialized; ///< Has Initialize() been called? 00265 CATStringTable* fStringTable; ///< String table to get strings from 00266 CATLangId fLangId; ///< Language Id (CATLANG_EN default) 00267 CATResult fPrefaceId; ///< String id of preface for PrintUsage() 00268 00269 std::vector<CATCMDLINEARG> fCmdTable; ///< List of commands 00270 std::vector<CATCmdArg*> fArguments; ///< List of parsed arguments 00271 std::vector<CATWChar*> fOperands; ///< List of parsed operands 00272 }; 00273 00274 #endif //_CATCmdLine_H_