qgetopt.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 * MeshLab                                                           o o     *
00003 * An extendible mesh processor                                    o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2005, 2009                                          \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 
00024 #include <stdlib.h>
00025 #include <assert.h>
00026 #include <QtCore/QVariant>
00027 #include "qgetopt.h"
00028 
00029 #include <iostream>
00030 using namespace std;
00031 
00032 GetOpt::GetOpt(int argc, char *argv[] ) {
00033   appname = argv[0];
00034   for(int i = 1; i < argc; i++)
00035     args.push_back(argv[i]);
00036 }
00037 
00038 GetOpt::GetOpt(const QStringList &a): args(a) {
00039   appname = a[0];
00040   args = a;
00041   args.pop_front();
00042 }
00043 
00044  //add an option without a value
00045 void GetOpt::addSwitch(char s, const QString &name, const QString &description, bool *b ) {
00046   Option option;
00047   assert(!findOption(s, option));
00048   assert(!findArg(name, option));
00049   option.type = Option::SWITCH;
00050   option.o = s;
00051   option.name = name;
00052   option.description = description;
00053   option.boolean_value = b;
00054   options.push_back(option);
00055 }
00056 
00057   //add a valued option (v will be left untouched if the option is not given)
00058 void GetOpt::addOption(char s, const QString &name, const QString &description, QVariant *v ) {
00059   Option option(Option::OPTION, s, name, description);
00060   option.value = v;
00061 
00062   assert(!findOption(s, option)); //TODO make this check systematic
00063   assert(!findArg(name, option));
00064 
00065   options.push_back(option);
00066 
00067 
00068 }
00069   //add an argument
00070 void GetOpt::addArgument(const QString &name, const QString &description, QVariant *v) {
00071   Option option;
00072   option.value = v;
00073   addArgument(name, description, option);
00074 }
00075 
00076 void GetOpt::addArgument(const QString &name, const QString &description, QString *v) {
00077   Option option;
00078   option.string_value = v;
00079   addArgument(name, description, option);
00080 }
00081 
00082 void GetOpt::addArgument(const QString &name, const QString &description, float *v) {
00083   Option option;
00084   option.float_value = v;
00085   addArgument(name, description, option);
00086 }
00087 
00088 void GetOpt::addArgument(const QString &name, const QString &description, double *v) {
00089   Option option;
00090   option.double_value = v;
00091   addArgument(name, description, option);
00092 }
00093 
00094 void GetOpt::addArgument(const QString &name, const QString &description, int *v) {
00095   Option option;
00096   option.int_value = v;
00097   addArgument(name, description, option);
00098 }
00099 
00100 void GetOpt::addArgument(const QString &name, const QString &description, bool *v) {
00101   Option option;
00102   option.boolean_value = v;
00103   addArgument(name, description, option);
00104 }
00105 
00106 void GetOpt::addArgument(const QString &name, const QString &description, Option option) {
00107     assert(!findArg(name, option));
00108     option.type = Option::ARGUMENT;
00109     option.name = name;
00110     option.description = description;
00111     options.push_back(option);
00112 }
00113 
00114 void GetOpt::addOption(char s, const QString &longname, const QString &description, QString *v) {
00115     Option option(Option::OPTION, s, longname, description);
00116     option.string_value = v;
00117     options.push_back(option);
00118 }
00119 void GetOpt::addOption(char s, const QString &longname, const QString &description, float *v) {
00120         Option option(Option::OPTION, s, longname, description);
00121         option.float_value = v;
00122         options.push_back(option);
00123 }
00124 void GetOpt::addOption(char s, const QString &longname, const QString &description, double *v) {
00125     Option option(Option::OPTION, s, longname, description);
00126     option.double_value = v;
00127     options.push_back(option);
00128 }
00129 void GetOpt::addOption(char s, const QString &longname, const QString &description, int *v) {
00130     Option option(Option::OPTION, s, longname, description);
00131     option.int_value = v;
00132     options.push_back(option);
00133 }
00134 void GetOpt::addOption(char s, const QString &longname, const QString &description, bool *v) {
00135     Option option(Option::OPTION, s, longname, description);
00136     option.boolean_value = v;
00137     options.push_back(option);
00138 }
00139 
00140   //add an optional agrument
00141 void GetOpt::addOptionalArgument(const QString &name, const QString &description, QVariant *v) {
00142   Option option;
00143   assert(!findArg(name, option));
00144   option.type = Option::OPTIONAL;
00145   option.name = name;
00146   option.description = description;
00147   option.value = v;
00148   options.push_back(option);
00149 }
00150   //return application name
00151 QString &GetOpt::applicationName() {
00152   return appname;
00153 }
00154 
00155   //return usage string
00156 QString GetOpt::usage() {
00157   QString u = "Usage: " + appname;
00158   //arguments
00159   bool has_optionals = false;
00160   bool has_options = false;
00161   for(int i = 0; i < options.size(); i++) {
00162     if(options[i].type == Option::OPTION) has_options = true;
00163     if(options[i].type == Option::OPTIONAL) has_optionals = true;
00164     if(options[i].type != Option::ARGUMENT) continue;
00165     u += " <" + options[i].name + ">";
00166   }
00167   //optional arguments
00168   if(has_optionals) {
00169     u += " [";
00170     for(int i = 0; i < options.size(); i++) {
00171       if(options[i].type != Option::OPTIONAL) continue;
00172       u += "<" + options[i].name + ">";
00173     }
00174     u += "]";
00175   }
00176   if(has_options) {
00177     u += " [-";
00178     for(int i = 0; i < options.size(); i++) {
00179       if(options[i].type != Option::OPTION) continue;
00180       u += options[i].o;
00181     }
00182     u += "]";
00183   }
00184   u += "\n\n";
00185   //compute maxlen:
00186   int maxlen = 0;
00187   for(int i = 0; i < options.size(); i++) {
00188     Option &o = options[i];
00189     int len = o.name.size() + 2;
00190     switch(o.type) {
00191       case Option::ARGUMENT:
00192       case Option::OPTIONAL: break;
00193       case Option::SWITCH:   len += 5; break;
00194       case Option::OPTION:   len += 16; break;
00195       default: break;
00196     }
00197     if(len > maxlen) maxlen = len;
00198   }
00199   //print options and arguments in the given order
00200   for(int i = 0; i < options.size(); i++) {
00201     Option &o = options[i];
00202     QString line = "";
00203     switch(o.type) {
00204       case Option::ARGUMENT:
00205       case Option::OPTIONAL: line += o.name; break;
00206       case Option::SWITCH:   line += "-" + QString(o.o) + " --" + o.name; break;
00207       case Option::OPTION:   line += "-" + QString(o.o) + " <val> --" + o.name + " <val>"; break;
00208       default: break;
00209     }
00210     QString blank = "";
00211     blank.resize(maxlen - line.size());
00212     blank.fill(' ');
00213     line += blank + formatDesc(o.description, maxlen) + "\n";
00214     u += line;
00215   }
00216   return u;
00217 }
00218 
00219 void GetOpt::parse() {
00220   QString error;
00221   if(!parse(error)) {
00222     cerr << qPrintable(error) << endl << endl << qPrintable(usage()) << endl << endl;
00223     exit(0);
00224   }
00225 }
00226 
00227 bool GetOpt::assignOption(Option &o, QString arg, QString &error) {
00228     QVariant::Type type;
00229     if(o.value) type = o.value->type();
00230     if(o.string_value) type = QVariant::String;
00231         if(o.float_value) type = QVariant::Double;
00232     if(o.double_value) type = QVariant::Double;
00233     if(o.int_value) type = QVariant::Int;
00234     if(o.boolean_value) type = QVariant::Bool;
00235     QVariant v(arg);
00236 
00237     if(!v.canConvert(type) || !v.convert(type)) {
00238       error = "Error while parsing option " + o.name + ": cannot convert " +
00239               arg + " to: " + v.typeName();
00240       return false;
00241     }
00242     if(o.value)         *(o.value)         = v;
00243     if(o.string_value)  *(o.string_value)  = v.toString();
00244         if(o.float_value)   *(o.float_value)   = v.toFloat();
00245         if(o.double_value)  *(o.double_value)  = v.toDouble();
00246     if(o.int_value)     *(o.int_value)     = v.toInt();
00247     if(o.boolean_value) *(o.boolean_value) = v.toBool();
00248     return true;
00249 }
00250 
00251 bool GetOpt::parse(QString &error) {
00252   for(int i = 0; i < args.size(); i++) {
00253     QString arg = args[i];
00254     if(args[i] == "-h" || args[i] == "--help") {
00255       cout << qPrintable(usage()) << endl << qPrintable(help) << endl;
00256       exit(0);
00257     }
00258     //long option
00259     if(arg.startsWith( QString::fromLatin1( "--" ) ) ) {
00260       arg = arg.mid( 2 );
00261       if(arg.isEmpty()) {
00262         error = "'--' feature not supported, yet";
00263         return false;
00264       }
00265       Option o;
00266       if(!findArg(arg, o)) {
00267          error = "Unknown option: '" + arg + "'";
00268         return false;
00269       }
00270       if(o.type == Option::SWITCH) {
00271         *(o.boolean_value) = true;
00272       } else { //OPTION
00273         i++;
00274         if(args.size() <= i) {
00275           error =  "Missing value for option: " + arg;
00276           return false;
00277         }
00278         arg = args[i];
00279         if(i == args.size() || arg[0] == '-') {
00280           error = "Missing argument after option '" + arg + "'";
00281           return false;
00282         }
00283         if(!assignOption(o, arg, error))
00284             return false;
00285       }
00286 
00287     //option
00288     } else if( arg[0] == '-' ) {
00289       if(arg.size() != 2) {
00290         error = "Invalid option: " + arg;
00291         return false;
00292       }
00293       Option o;
00294       if(!findOption(arg[1].toLatin1(), o)) {
00295          error = "Unknown option: '" + arg + "'";
00296         return false;
00297       }
00298       if(o.type == Option::SWITCH) {
00299         *(o.boolean_value) = true;
00300       } else { //OPTION
00301         i++;
00302         if(args.size() <= i) {
00303           error =  "Missing value for option: " + arg;
00304           return false;
00305         }
00306         arg = args[i];
00307         if(i == args.size()) {
00308           error = "Missing argument after option '" + arg + "'";
00309           return false;
00310         }
00311         if(!assignOption(o, arg, error))
00312             return false;
00313 /*
00314         QVariant v(arg);
00315         if(!v.canConvert(o.value->type()) || !v.convert(o.value->type())) {
00316           error = "Error while parsing option " + o.name + ": cannot convert " +
00317                   arg + " to: " + o.value->typeName();
00318           return false;
00319         }
00320         *(o.value) = v; */
00321       }
00322     //argument
00323     } else {
00324       arguments.push_back(arg);
00325     }
00326   }
00327 
00328   //regular arguments
00329   for(int i = 0; i < options.size(); i++) {
00330     Option &o = options[i];
00331     if(o.type != Option::ARGUMENT) continue;
00332     if(arguments.isEmpty()) {
00333       error = "Too few arguments, could not parse argument '" + o.name + "'";
00334       return false;
00335     }
00336     if(!assignOption(o, arguments.front(), error))
00337         return false;
00338     arguments.pop_front();
00339   }
00340    //optional arguments
00341   for(int i = 0; i < options.size(); i++) {
00342     Option &o = options[i];
00343     if(o.type != Option::OPTIONAL) continue;
00344     if(arguments.isEmpty()) break;
00345     if(!assignOption(o, arguments.front(), error))
00346         return false;
00347     arguments.pop_front();
00348   }
00349   if(!arguments.isEmpty() && !unlimitedArgs) {
00350     error = "Too many arguments";
00351     return false;
00352   }
00353   return true;
00354 }
00355 
00356 bool GetOpt::findOption(char c, Option &option) {
00357   for(int i = 0; i < options.size(); i++) {
00358     Option &o = options[i];
00359     if(o.type != Option::OPTION && o.type != Option::SWITCH) continue;
00360     if(o.o == c) {
00361       option = o;
00362       return true;
00363     }
00364   }
00365   return false;
00366 }
00367 
00368 bool GetOpt::findArg(const QString &name, Option &option) {
00369   for(int i = 0; i < options.size(); i++) {
00370     Option &o = options[i];
00371     if(o.name == name) {
00372       option = o;
00373       return true;
00374     }
00375   }
00376   return false;
00377 }
00378 
00379 QString GetOpt::formatDesc(QString desc, int len) {
00380   QString output;
00381   //search for last space before 79 - len characters
00382   while(!desc.isEmpty()) {
00383     int pos = desc.lastIndexOf(" ", 79 - len);
00384     if(pos == -1) {
00385       output += desc;
00386       break;
00387     }
00388     output += desc.left(pos) + "\n";
00389     QString blank;
00390     blank.resize(len);
00391     blank.fill(' ');
00392     output += blank;
00393     desc = desc.mid(pos+1);
00394   }
00395   return output;
00396 }


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:34:44