00001 #ifndef ARG_PARSER_H 00002 #define ARG_PARSER_H 00003 00004 //-------------------------------------------------------------------- 00005 // 00006 // This file is part of PEACE. 00007 // 00008 // PEACE is free software: you can redistribute it and/or modify it 00009 // under the terms of the GNU General Public License as published by 00010 // the Free Software Foundation, either version 3 of the License, or 00011 // (at your option) any later version. 00012 // 00013 // PEACE is distributed in the hope that it will be useful, but 00014 // WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU General Public License 00019 // along with PEACE. If not, see <http://www.gnu.org/licenses/>. 00020 // 00021 // Miami University makes no representations or warranties about the 00022 // suitability of the software, either express or implied, including 00023 // but not limited to the implied warranties of merchantability, 00024 // fitness for a particular purpose, or non-infringement. Miami 00025 // University shall not be liable for any damages suffered by licensee 00026 // as a result of using, result of using, modifying or distributing 00027 // this software or its derivatives. 00028 // 00029 // By using or copying this Software, Licensee agrees to abide by the 00030 // intellectual property laws, and all other applicable laws of the 00031 // U.S., and the terms of GNU General Public License (version 3). 00032 // 00033 // Authors: Dhananjai M. Rao raodm@muohio.edu 00034 // 00035 //--------------------------------------------------------------------- 00036 00037 #include <cstdlib> 00038 #include <cstring> 00039 #include <string> 00040 #include <iostream> 00041 00042 class arg_parser { 00043 00044 // @BeginExternalProseDescription 00045 00046 // This file contains the declarations for a class which accepts a list of 00047 // arguments with addresses of the variables they affect, and parses argv 00048 // and argc to check for them. Errors are dealt with as well. The 00049 // variables can either be boolean, char*, or dl_list<char*>; 00050 // which type a variable is is determined by a value of the enumerated 00051 // type arg_parser::arg_type. 00052 00053 // Here is an example of the use of this class: 00054 // 00055 // bool arg1; // These must be static or global scope... 00056 // bool arg2; 00057 // char *arg3; 00058 // 00059 // arg_parser::arg_record arg_list[] = { 00060 // { "-arg1", &arg1, arg_parser::BOOLEAN }, 00061 // { "-arg2", &arg2, arg_parser::BOOLEAN }, 00062 // { "-arg3", &arg3, arg_parser::STRING }, 00063 // { NULL, NULL } 00064 // }; 00065 // 00066 // 00067 // int main( int argc, char *argv[] ){ 00068 // arg1 = true; // default initialization must occur before the 00069 // arg2 = false; // arg_parser is called! 00070 // arg3 = NULL; 00071 // 00072 // arg_parser ap( arg_list ); 00073 // ap.check_args( argc, argv ); 00074 00075 // @EndExternalProseDescription 00076 00077 friend std::ostream &operator<<(std::ostream &, const arg_parser &); 00078 00079 public: 00080 enum arg_type {BOOLEAN, INTEGER, STRING, STRING_LIST, FLOAT, 00081 DOUBLE, LONG_LONG}; 00082 00083 struct arg_record { 00084 const char *arg_text; 00085 const char *arg_help; 00086 void *data; 00087 arg_type type; 00088 }; 00089 00090 arg_record last_arg; 00091 00092 arg_parser() { 00093 array_of_arg_records = NULL; 00094 num_args = 0; 00095 } 00096 00097 arg_parser(arg_record *record_ptr) { 00098 get_arg_array(record_ptr); 00099 } 00100 00101 ~arg_parser() {} 00102 00103 void get_arg_array(arg_record[]); 00104 00105 // The int is the number of args (argc), the char ** is argv, and 00106 // the bool is whether to complain and exit on error or not... 00107 bool check_args(int &argc, char *argv[], bool caxoe = true ); 00108 00109 static void set_global_args(int argc, const char* const argv[]); 00110 static std::string get_global_args() { return global_args; } 00111 00112 private: 00113 arg_record *array_of_arg_records; 00114 int num_args; 00115 00116 // This method is used to pull arguments from the command line as 00117 // they're processed... 00118 void remove_arg( int arg_to_remove, int &argc, char **argv); 00119 00120 // This method checks the arguments passed in to see if there are any 00121 // in the form "-blah" and complains, if the global var 00122 // "complain_and_exit_on_error" is set to true. 00123 bool check_remaining( int argc, char **argv, 00124 bool complain_and_exit_on_error); 00125 00126 // The global set of arguments. This must be set from the main() 00127 // method via the set_global_args() method. The global arguments 00128 // serve as a place holder to preserve global arguments in the form 00129 // of a single string. This information is typically used in logs 00130 // etc. 00131 static std::string global_args; 00132 }; 00133 00134 inline 00135 std::ostream &operator<<(std::ostream &os, const arg_parser &ap){ 00136 const int num_spaces = 3; 00137 const int indentation = 2; 00138 00139 // calculate the length of the longest argument 00140 int i = 0; 00141 int maxlen = 0; 00142 while( ap.array_of_arg_records[i].arg_text != NULL ){ 00143 if( (int) strlen(ap.array_of_arg_records[i].arg_text) > maxlen ){ 00144 maxlen = (int) strlen(ap.array_of_arg_records[i].arg_text); 00145 } 00146 i++; 00147 } 00148 if (maxlen < 12) { 00149 maxlen = 12; 00150 } 00151 00152 // print the argument array 00153 int j; 00154 i = 0; 00155 while( ap.array_of_arg_records[i].arg_text != NULL ){ 00156 00157 // indent the proper amount 00158 for( j = 0; j < indentation; j++ ){ 00159 os << " "; 00160 } 00161 00162 // here is the argument 00163 os << ap.array_of_arg_records[i].arg_text; 00164 00165 // print out the padding - leave num_spaces spaces between args and 00166 // help text... 00167 for( j = 0; j < (int) (maxlen - strlen(ap.array_of_arg_records[i].arg_text) 00168 + num_spaces); j++ ){ 00169 os << " "; 00170 } 00171 00172 // here is the help string. 00173 os << ap.array_of_arg_records[i].arg_help << std::endl; 00174 i++; 00175 } 00176 00177 // for( j = 0; j < indentation; j++ ){ 00178 // os << " "; 00179 // } 00180 00181 // os << "-help"; 00182 // for( j = 0; j < (int) (maxlen - strlen("-help") + num_spaces) ; j++ ){ 00183 // os << " "; 00184 // } 00185 // os << "print this message" << std::endl; 00186 00187 return os; 00188 } 00189 00190 #endif