Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

QgarArgs.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------+
00002  | Library QgarLib, graphics analysis and recognition                  |
00003  | Copyright (C) 2002  Qgar Project, LORIA                             |
00004  |                                                                     |
00005  | This library is free software; you can redistribute it and/or       |
00006  | modify it under the terms of the GNU Lesser General Public          |
00007  | License version 2.1, as published by the Free Software Foundation.  |
00008  |                                                                     |
00009  | This library is distributed in the hope that it will be useful,     |
00010  | but WITHOUT ANY WARRANTY; without even the implied warranty of      |
00011  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                |
00012  | See the GNU Lesser General Public License for more details.         |
00013  |                                                                     |
00014  | The GNU Lesser General Public License is included in the file       |
00015  | LICENSE.LGPL, in the root directory of the Qgar packaging. See      |
00016  | http://www.gnu.org/licenses/lgpl.html for the terms of the licence. |
00017  | To receive a paper copy, write to the Free Software Foundation,     |
00018  | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.       |
00019  |                                                                     |
00020  | Contact Project Qgar for any information:                           |
00021  |   LORIA - équipe Qgar                                               |
00022  |   B.P. 239, 54506 Vandoeuvre-lès-Nancy Cedex, France                |
00023  |   email: qgar-contact@loria.fr                                      |
00024  |   http://www.qgar.org/                                              |
00025  *---------------------------------------------------------------------*/
00026 
00027 
00028 
00029 /**
00030  * @file    QgarArgs.C
00031  * @brief   Implementation of class qgar::QgarArgs.
00032  *
00033  * See file QgarArgs.H for the interface.
00034  *
00035  * @author   <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Philippe Dosch">Philippe Dosch</a>
00036  * @date     July 2, 2001  17:22
00037  * @since    Qgar 1.0
00038  */
00039 
00040 
00041 
00042 // STL
00043 #include <iostream>
00044 #include <cstring>
00045 #include <cstdlib>
00046 #include <sstream>
00047 #include <string>
00048 // QGAR
00049 #include <qgarlib/QgarArgs.H>
00050 #include <qgarlib/QgarErrorUser.H>
00051 
00052 
00053 
00054 using namespace std;
00055 using namespace qgar;
00056 
00057 
00058 
00059 namespace qgar
00060 {
00061 
00062 
00063 /*-------------------------------------------------------------------*
00064  |                                                                   |
00065  |                 I N N E R   C L A S S   QgarParam                 |
00066  |                                                                   |
00067  *-------------------------------------------------------------------*/
00068 
00069 
00070 // ============
00071 // CONSTRUCTORS
00072 // ============
00073 
00074 // DEFAULT CONSTRUCTOR
00075 
00076 QgarArgs::QgarParam::QgarParam(const char* aParamName,
00077                                QGEparamStatus aParamStatus,
00078                                QGEparamType aParamType,
00079                                const char* aDescription,
00080                                const char* anExtension,
00081                                const char* aDefault)
00082 
00083   : _name(aParamName),
00084     _description(aDescription),
00085     _useFlag(false),
00086     _paramStatus(aParamStatus),
00087     _paramType(aParamType),
00088     _extension(anExtension),
00089     _default(aDefault),
00090     _value(0),
00091     _newValue(false)
00092 
00093 {
00094   // VOID
00095 }
00096 
00097 
00098 // ======
00099 // ACCESS
00100 // ======
00101 
00102 
00103 const char*
00104 QgarArgs::QgarParam::value(bool aSpecial)
00105 {
00106   if(aSpecial)
00107     {
00108       _newValue = false;
00109     }
00110 
00111   return _value;
00112 }
00113 
00114 
00115 // =======
00116 // DISPLAY
00117 // =======
00118 
00119 
00120 // DISPLAY INFORMATION ABOUT THE PARAMETER ON STANDARD OUTPUT
00121 
00122 void
00123 QgarArgs::QgarParam::printGUI(bool anEndl) const
00124 {
00125   cout << _name << ';'          // parameter flag
00126        << _description << ';';  // description
00127 
00128   // Parameter type
00129   switch(_paramType)
00130     {
00131     case INT:
00132       cout << "int";
00133       break;
00134     case FLOAT:
00135       cout << "float";
00136       break;
00137     case STRING:
00138       cout << "string";
00139       break;
00140     case BOOL:
00141       cout << "bool";
00142       break;
00143     case FILEIN:
00144       cout << "in";
00145       break;
00146     case FILEOUT:
00147       cout << "out";
00148       break;
00149     case FILEOUTD:
00150       cout << "outd";
00151       break;
00152     case FILEOUTDS:
00153       cout << "outds";
00154       break;
00155     case PATH:
00156       cout << "path";
00157       break;
00158     }
00159   cout << ';';
00160 
00161   // Required or optional
00162   if (_paramStatus == REQPARAM || _paramStatus == REQMULTIPARAM)
00163     {
00164       cout << 'R';
00165     }
00166   else
00167     {
00168       cout << 'O';
00169     }
00170   cout << ';';
00171 
00172   // Extension or default value, according to parameter type
00173 
00174   if (_paramType == INT ||
00175       _paramType == FLOAT ||
00176       _paramType == STRING ||
00177       _paramType == BOOL)
00178     {
00179       if (_default)
00180         {
00181           cout << _default;
00182         }
00183     }
00184   else
00185     {
00186       if (_extension)
00187         {
00188           cout << _extension;
00189         }
00190     }
00191   cout << ';';
00192   
00193   if(anEndl)
00194     {
00195       cout << std::endl;
00196     }
00197 }
00198 
00199 
00200 
00201 // DISPLAY USAGE MESSAGE ON STANDARD OUTPUT
00202 
00203 void
00204 QgarArgs::QgarParam::showUsage() const
00205 {
00206     cout << _description           // parameter description
00207          << ' ' << _name << " (";  // parameter name
00208 
00209     // Parameter type
00210     switch(_paramType)
00211       {
00212       case INT:
00213         cout << "int";
00214         break;
00215       case FLOAT:
00216         cout << "float";
00217         break;
00218       case STRING:
00219         cout << "string";
00220         break;
00221       case BOOL:
00222         cout << "bool";
00223         break;
00224       case FILEIN:
00225       case FILEOUT:
00226       case FILEOUTD:
00227       case FILEOUTDS:
00228         cout << "filename";
00229         break;
00230       case PATH:
00231         cout << "path";
00232         break;
00233       }  
00234     cout << ", ";
00235 
00236   // Parameter status
00237   if ((_paramStatus == REQPARAM) || (_paramStatus == REQMULTIPARAM))
00238     {
00239       cout << "Required";
00240     }
00241   else
00242     {
00243       cout << "Optional";
00244     }
00245 
00246   cout << ')' << std::endl;
00247 }
00248 
00249 
00250 
00251 /*-------------------------------------------------------------------*
00252  |                                                                   |
00253  |                        C L A S S   QgarArgs                       |
00254  |                                                                   |
00255  *-------------------------------------------------------------------*/
00256 
00257 
00258 
00259 // ============
00260 // CONSTRUCTORS
00261 // ============
00262 
00263 
00264 // DEFAULT CONSTRUCTOR
00265 
00266 QgarArgs::QgarArgs()
00267 
00268   : _description(0),
00269     _exit(false),
00270     _error(false),
00271     _interactive(false)
00272 
00273 {
00274   // VOID
00275 }
00276 
00277 
00278 // ==========
00279 // DESTRUCTOR
00280 // ==========
00281 
00282 
00283 QgarArgs::~QgarArgs()
00284 {
00285   list<QgarParam*>::iterator itP;
00286 
00287   for (itP = _args.begin(); itP != _args.end(); ++itP)
00288     {
00289       delete *itP;
00290     }
00291 
00292   if (_description)
00293     {
00294       delete [] _description;
00295     }
00296 }
00297 
00298 
00299 // ============
00300 // COMMAND LINE
00301 // ============
00302 
00303 
00304 // ANALYZE THE COMMAND LINE
00305 
00306 void
00307 QgarArgs::analyzeLine(int argc, char * argv[])
00308 {
00309   int i = 1;
00310 
00311   while (i < argc)
00312     {
00313       QgarParam* pParam = findParam(argv[i]);
00314 
00315       // If the parameter is not recognized, try flags -h and -gui
00316 
00317       if (!pParam)
00318         {
00319           if (!strcmp("-h", argv[i]))
00320             {
00321               _exit = true;
00322               showUsage(argv[0]);
00323             }
00324           else
00325             {
00326               if (!strcmp("-gui", argv[i]))
00327                 {
00328                   _exit = true;
00329                   printGUI();
00330                 }
00331               else
00332                 {
00333                   if (!strcmp("-interact", argv[i]))
00334                     {
00335                       _interactive = true;
00336                     }
00337                   else
00338                     {
00339                       _error = true;
00340                       cerr << "QGAR: ERROR NOTIFIED BY AN APPLICATION" << endl
00341                            << ">>> Bad flag: " << argv[i] << endl;
00342                     }
00343                 }
00344             }
00345 
00346           return;
00347         }
00348 
00349  
00350       switch (pParam->paramStatus())
00351         {
00352           // --------------------------------------------------------
00353           case SINGLEFLAG:
00354 
00355             pParam->setUseFlag();
00356             break;
00357 
00358           // --------------------------------------------------------
00359           case REQPARAM:
00360           case OPTPARAM:
00361 
00362             ++i;
00363 
00364             if (i == argc)
00365               {
00366                 _error = true;
00367                 cerr << "QGAR: ERROR NOTIFIED BY AN APPLICATION" << endl
00368                      << ">>> No value for flag "        << argv[i-1] << endl;
00369                 return;
00370               }
00371       
00372             if (findParam(argv[i]))
00373               {
00374                 _error = true;
00375                 cerr << "QGAR: ERROR NOTIFIED BY AN APPLICATION" << endl
00376                      << ">>> Bad value for flag " << argv[i - 1] << ": "
00377                      << argv[i] << endl;
00378                 return;
00379               }
00380       
00381           pParam->setValue(argv[i]);
00382           pParam->setUseFlag();
00383           break;
00384 
00385           // --------------------------------------------------------
00386           case REQMULTIPARAM:
00387           case OPTMULTIPARAM:
00388 
00389             ++i;
00390 
00391             if (i == argc)
00392               {
00393                 _error = true;
00394                 cerr << "QGAR: ERROR NOTIFIED BY AN APPLICATION" << endl
00395                      << ">>> No value for flag " << argv[i-1] << endl;
00396                 return;
00397               }
00398       
00399             if (findParam(argv[i]))
00400               {
00401                 _error = true;
00402                 cerr << "QGAR: ERROR NOTIFIED BY AN APPLICATION" << endl
00403                      << ">>> Bad value for flag " << argv[i - 1] << ": "
00404                      << argv[i] << endl;
00405                 return;
00406               }
00407 
00408             do
00409               {
00410                 pParam->addArgument(argv[i]);
00411                 ++i;
00412               }
00413             while ((i < argc) && (findParam(argv[i])));
00414 
00415             pParam->setUseFlag();
00416             --i;
00417             break;
00418 
00419           // --------------------------------------------------------
00420         } // END switch
00421     
00422       // Next argument
00423       ++i;
00424 
00425     } // END while
00426 
00427 
00428   // All the arguments are processed
00429   // Check required parameters
00430   
00431   for (list<QgarParam*>::iterator it = _args.begin();
00432        it != _args.end();
00433        ++it)
00434     {
00435       if ((((*it)->paramStatus() == REQPARAM) || ((*it)->paramStatus() == REQMULTIPARAM))
00436           && !((*it)->useFlag()))
00437         {
00438           _error = true;
00439           cerr << "QGAR: ERROR NOTIFIED BY AN APPLICATION" << endl
00440                << ">>> Missing flag: " << (*it)->name() << endl;
00441           return;
00442         }
00443     }
00444 }
00445 
00446 
00447 // ==========
00448 // PREDICATES
00449 // ==========
00450 
00451 
00452 // IS GIVEN FLAG SET?
00453 
00454 bool
00455 QgarArgs::isOptionSet(const char *aFlag) const
00456 {
00457   QgarParam* pParam = findParam(aFlag);
00458 
00459   // The parameter must be declared
00460   if (pParam == 0)
00461     {
00462       std::ostringstream os;
00463       os << "Unknown flag: "
00464          << aFlag;
00465       throw QgarErrorUser(__FILE__, __LINE__,
00466                           "bool qgar::QgarArgs::isOptionSet(const char*) const",
00467                           os.str());
00468     }
00469 
00470   // The flag must be optional
00471   if ((pParam->paramStatus() != SINGLEFLAG) &&
00472       (pParam->paramStatus() != OPTPARAM)   &&
00473       (pParam->paramStatus() != OPTMULTIPARAM))
00474     {
00475       std::ostringstream os;
00476       os << "Flag "
00477          << aFlag
00478          << " should be optional.";
00479       throw QgarErrorUser(__FILE__, __LINE__,
00480                           "bool qgar::QgarArgs::isOptionSet(const char*) const",
00481                           os.str());
00482     }
00483 
00484   return pParam->useFlag();
00485 }
00486 
00487 
00488 // ======
00489 // ACCESS
00490 // ======
00491 
00492 
00493 // GET THE STRING ASSOCIATED WITH A PARAMETER
00494 
00495 const char*
00496 QgarArgs::getStringOption(const char* aFlag, bool aSpecial) const
00497 {
00498   QgarParam* pParam = findParam(aFlag);
00499 
00500   // The parameter must be declared
00501   if (pParam == 0)
00502     {
00503       std::ostringstream os;
00504       os << "Unknown flag: "
00505          << aFlag;
00506       throw QgarErrorUser(__FILE__, __LINE__,
00507                           "const char* qgar::QgarArgs::getStringOption(const char*, bool) const",
00508                           os.str());
00509     }
00510 
00511   // The flag must match a single parameter
00512   if ((pParam->paramStatus() != OPTPARAM) && (pParam->paramStatus() != REQPARAM))
00513     {
00514       std::ostringstream os;
00515       os << "Flag "
00516          << aFlag
00517          << " should match a single parameter.";
00518       throw QgarErrorUser(__FILE__, __LINE__,
00519                           "const char* qgar::QgarArgs::getStringOption(const char*, bool) const",
00520                           os.str());
00521     }
00522 
00523   return pParam->value(aSpecial);
00524 }
00525 
00526 
00527 // GET THE NUMBER OF STRINGS
00528 
00529 int
00530 QgarArgs::getNumberOptions(const char* aFlag) const
00531 {
00532   QgarParam* pParam = findParam(aFlag);
00533 
00534   // The parameter must be declared
00535   if (pParam == 0)
00536     {
00537       std::ostringstream os;
00538       os << "Unknown flag: "
00539          << aFlag;
00540       throw QgarErrorUser(__FILE__, __LINE__,
00541                           "int qgar::QgarArgs::getNumberOptions(const char*) const",
00542                           os.str());
00543     }
00544 
00545   // The flag must match a multi-valued parameter
00546   if ((pParam->paramStatus() != OPTMULTIPARAM) && (pParam->paramStatus() != REQMULTIPARAM))
00547     {
00548       std::ostringstream os;
00549       os << "Flag "
00550          << aFlag
00551          << " should match a multi-valued parameter.";
00552       throw QgarErrorUser(__FILE__, __LINE__,
00553                           "int qgar::QgarArgs::getNumberOptions(const char*) const",
00554                           os.str());
00555     }
00556 
00557   return pParam->numbOptions();
00558 }
00559 
00560 
00561 // GET STRING INDEX ASSOCIATED WITH A MULTI-VALUED PARAMETER
00562 
00563 const char*
00564 QgarArgs::getStringOptionMulti (const char* aFlag, int anIdx) const
00565 {
00566   QgarParam* pParam = findParam(aFlag);
00567 
00568   // The parameter must be declared
00569   if (pParam == 0)
00570     {
00571       std::ostringstream os;
00572       os << "Unknown flag: "
00573          << aFlag;
00574       throw QgarErrorUser(__FILE__, __LINE__,
00575                           "const char* qgar::QgarArgs::getStringOptionMulti (const char*, int) const",
00576                           os.str());
00577     }
00578 
00579   // The flag must match a multi-valued parameter and a valid index
00580   if (   ( (pParam->paramStatus() != OPTMULTIPARAM) &&
00581            (pParam->paramStatus() != REQMULTIPARAM)    )
00582       ||
00583          (anIdx > pParam->numbOptions()))
00584     {
00585       std::ostringstream os;
00586       os << "Flag "
00587          << aFlag
00588          << " should match a multi-valued parameter and a valid index.";
00589       throw QgarErrorUser(__FILE__, __LINE__,
00590                           "const char* qgar::QgarArgs::getStringOptionMulti (const char*, int) const",
00591                           os.str());
00592     }
00593 
00594   return pParam->argument(anIdx);
00595 }
00596 
00597 
00598 // GET THE PARAMETER DESCRIPTION
00599 
00600 QgarArgs::QgarParam*
00601 QgarArgs::findParam(const char* aParam) const
00602 {
00603   list<QgarParam*>::const_iterator it;
00604   bool found = false;
00605   
00606   for (it = _args.begin(); it != _args.end(); ++it)
00607     {
00608       if (!strcmp(aParam, (*it)->name()))
00609         {
00610           found = true;
00611           break;
00612         }
00613     }
00614 
00615   return (found) ? (*it) : 0;
00616 }
00617 
00618 
00619 // ==============
00620 // TRANSFORMATION
00621 // ==============
00622 
00623 
00624 // DECLARE GLOBAL INFORMATION ABOUT THE PARAMETER
00625 
00626 void
00627 QgarArgs::setDescription(const char* aDescription,
00628                          QGEfileType aFileType)
00629 {
00630   _fileType = aFileType;
00631 
00632   _description = new char[strlen(aDescription) + 1];
00633   strcpy(_description, aDescription);
00634 }
00635 
00636 
00637 // DECLARE A PARAMETER
00638 
00639 void
00640 QgarArgs::addParameter(const char* aParamName,
00641                        QGEparamStatus aParamStatus,
00642                        QGEparamType aParamType,
00643                        const char* aDescription,
00644                        const char* anExtension,
00645                        const char* aDefault)
00646 {
00647   _args.push_back(new QgarParam(aParamName,
00648                                 aParamStatus,
00649                                 aParamType,
00650                                 aDescription,
00651                                 anExtension,
00652                                 aDefault));
00653 }
00654 
00655 
00656 // SET THE PARAMETER VALUE
00657 
00658 void 
00659 QgarArgs::setParamValue(char* aFlag, char* aVal)
00660 {
00661   string tmp("-");
00662   tmp += aFlag;
00663 
00664   QgarParam* pParam = findParam(tmp.c_str());
00665 
00666   if (pParam == 0)
00667     {
00668       std::ostringstream os;
00669       os << "Unknown flag: "
00670          << aFlag;
00671       throw QgarErrorUser(__FILE__, __LINE__,
00672                           "void qgar::QgarArgs::setParamValue(char*, char*)",
00673                           os.str());
00674     }
00675 
00676   pParam->setNewValue(aVal);
00677 }
00678 
00679 
00680 // ===================
00681 // DISPLAY (protected)
00682 // ===================
00683 
00684 
00685 // DISPALY PARAMETERS
00686 
00687 void
00688 QgarArgs::printGUI() const
00689 {
00690   // Source file type and description must be set
00691   if (_description == 0)
00692     {
00693       throw QgarErrorUser(__FILE__, __LINE__,
00694                           "void qgar::QgarArgs::printGUI()",
00695                           "The description of the application is not available.");
00696     }
00697 
00698 
00699   // The type of the expected source file
00700   switch(_fileType)
00701     {
00702       case PPM:
00703         cout << "PPM";
00704         break;
00705       case PGM:
00706         cout << "PGM";
00707         break;
00708       case PBM:
00709         cout << "PBM";
00710         break;
00711       case DXF:
00712         cout << "DXF";
00713         break;
00714     }
00715   cout << endl;
00716 
00717   // The description of the application (menu entry in GUI)
00718   cout << _description << endl;
00719 
00720   // A line for each of the parameter
00721   for (list<QgarParam*>::const_iterator it = _args.begin();
00722        it != _args.end() ;
00723        ++it)
00724     {
00725       (*it)->printGUI(true);
00726     }
00727 }
00728 
00729 
00730 // DISPLAY USAGE MESSAGE
00731 
00732 void
00733 QgarArgs::showUsage(const char* aCommand) const
00734 {
00735   cout << "QGAR: USAGE FOR APPLICATION " << aCommand << ": "
00736        << _description << endl
00737        << ">>> Parameters:" << endl;
00738 
00739   for (list<QgarParam*>::const_iterator it = _args.begin();
00740        it != _args.end() ;
00741        ++it)
00742     {
00743       (*it)->showUsage();
00744     }
00745 }
00746 
00747 
00748 /*-------------------------------------------------------------------*
00749  |                                                                   |
00750  *-------------------------------------------------------------------*/
00751 
00752 
00753 } // namespace qgar