Main Page | Class Hierarchy | Class List | Directories | File List | Class Members

getpot.h

00001 // $Id: getpot.h,v 1.1.1.1 2003/04/17 11:38:23 rtmclay Exp $
00002 //
00003 // (with patches from Michael Anderson for more general variable types)
00004 
00005 //  -*- c++ -*- 
00006 //  GetPot Version 1.0                                        Sept/13/2002
00007 //  
00008 //  WEBSITE: http://getpot.sourceforge.net
00009 //  
00010 //  This library is  free software; you can redistribute  it and/or modify
00011 //  it  under  the terms  of  the GNU  Lesser  General  Public License  as
00012 //  published by the  Free Software Foundation; either version  2.1 of the
00013 //  License, or (at your option) any later version.
00014 //  
00015 //  This library  is distributed in the  hope that it will  be useful, but
00016 //  WITHOUT   ANY  WARRANTY;   without  even   the  implied   warranty  of
00017 //  MERCHANTABILITY  or FITNESS  FOR A  PARTICULAR PURPOSE.   See  the GNU
00018 //  Lesser General Public License for more details.
00019 //  
00020 //  You  should have  received a  copy of  the GNU  Lesser  General Public
00021 //  License along  with this library; if  not, write to  the Free Software
00022 //  Foundation, Inc.,  59 Temple Place,  Suite 330, Boston,  MA 02111-1307
00023 //  USA
00024 //  
00025 //  (C) 2001-2002 Frank R. Schaefer  
00026 //==========================================================================
00027 #ifndef __GETPOT_H__
00028 #define __GETPOT_H__
00029 
00030 #if defined(WIN32) || defined(__SUNPRO_CC) || (__GNUC__ == 2) || defined(__HP_aCC)
00031 #define strtok_r(a, b, c) strtok(a, b)
00032 #endif // WINDOWS or SOLARIS or gcc 2.* or HP aCC
00033 
00034 
00035 #define GETPOT_ALLOW_VARGS
00036 
00037 extern "C" {
00038 #include <ctype.h> 
00039 #include <stdio.h>
00040 
00041 #ifdef GETPOT_ALLOW_VARGS
00042 #include <stdarg.h>
00043 #endif
00044 
00045 }
00046 
00047 #include <math.h>
00048 
00049 #include <iostream>
00050 #include <string>
00051 #include <vector>
00052 #include <algorithm>
00053 #include <fstream>
00054 
00055 
00056 #define victorate(TYPE, VARIABLE, ITERATOR) \
00057 for(std::vector<TYPE>::const_iterator (ITERATOR) = (VARIABLE).begin(); \
00058     (ITERATOR) != (VARIABLE).end(); ++(ITERATOR))
00059 
00060 
00061 class GetPot {
00062   //--------
00063   inline void __basic_initialization();
00064   public:
00065   // (*) constructors, destructor, assignment operator -----------------------
00066   inline GetPot();
00067   inline GetPot(const GetPot&);
00068   inline GetPot(int argc_, char * argv_[]);
00069   inline ~GetPot();
00070   inline GetPot& operator=(const GetPot&);
00071 
00072   // (*) direct access to command line arguments -----------------------------
00073   inline const char*  operator[](unsigned Idx) const;
00074   inline int          get(unsigned Idx, int         Default) const;
00075   inline double       get(unsigned Idx, double      Default) const;
00076   inline const char*  get(unsigned Idx, const char* Default) const;
00077   inline unsigned     size() const; 
00078 
00079   // (*) flags ---------------------------------------------------------------
00080   inline bool   options_contain(const char* FlagList) const;
00081   inline bool   argument_contains(unsigned Idx, const char* FlagList) const;
00082 
00083   // (*) variables -----------------------------------------------------------
00084   //     -- scalar values
00085   inline bool         operator()(const char* VarName, bool        Default) const;
00086   inline int          operator()(const char* VarName, int         Default) const;
00087   inline double       operator()(const char* VarName, double      Default) const;
00088   inline const char*  operator()(const char* VarName, const char* Default) const;
00089   inline std::string  operator()(const char* VarName, const std::string& Default) const;
00090   //     -- vectors
00091   inline int          operator()(const char* VarName, int         Default, unsigned Idx) const;
00092   inline double       operator()(const char* VarName, double      Default, unsigned Idx) const;
00093   inline const char*  operator()(const char* VarName, const char* Default, unsigned Idx) const;
00094   inline unsigned       vector_variable_size(const char* VarName) const;
00095   inline std::vector<std::string> get_variable_names() const;
00096   inline std::vector<std::string> get_section_names() const;
00097 
00098 
00099   // (*) cursor oriented functions -------------------------------------------
00100   inline void         set_prefix(const char* Prefix) { prefix = std::string(Prefix); }
00101   inline void         set_prefix(const std::string & Prefix) { prefix = Prefix; }
00102   inline bool         search_failed() const { return search_failed_f; }
00103 
00104   //     -- enable/disable search for an option in loop
00105   inline void         disable_loop() { search_loop_f = false; }
00106   inline void         enable_loop()  { search_loop_f = true; }
00107 
00108   //     -- reset cursor to position '1'
00109   inline void         reset_cursor();
00110   inline void         init_multiple_occurrence();
00111 
00112   //     -- search for a certain option and set cursor to position
00113   inline bool         search(const char* option);
00114   inline bool         search(const std::string &option);
00115 
00116 
00117 #ifdef GETPOT_ALLOW_VARGS
00118   // TODO:    BAD USING VARGS
00119     inline bool         search(unsigned No, const char* P, ...);
00120 #endif
00121 
00122   //     -- get argument at cursor++
00123   inline int          next(int           Default);
00124   inline double       next(double Default);
00125   inline const char*  next(const char*   Default);
00126   inline std::string  next(const std::string   &Default);
00127   
00128   //     -- search for option and get argument at cursor++
00129   inline int          follow(int           Default, const char* Option);
00130   inline double       follow(double Default, const char* Option);
00131   inline const char*  follow(const char*   Default, const char* Option);
00132 
00133   //     -- search for one of the given options and get argument that follows it
00134 #ifdef GETPOT_ALLOW_VARGS
00135   // TODO:    BAD USING VARGS
00136   inline int          follow(int           Default, unsigned No, const char* Option, ...);
00137   inline double       follow(double Default, unsigned No, const char* Option, ...);
00138   inline const char*  follow(const char*   Default, unsigned No, const char* Option, ...);
00139 #endif
00140 
00141   //     -- directly followed arguments 
00142   inline int          direct_follow(int           Default, const char* Option);
00143   inline double       direct_follow(double Default, const char* Option);
00144   inline const char*  direct_follow(const char*   Default, const char* Option);
00145 
00146   // (*) nominus arguments ---------------------------------------------------
00147   inline void            reset_nominus_cursor();
00148   inline std::vector<std::string>  nominus_vector() const;
00149   inline unsigned        nominus_size() const  { return idx_nominus.size(); }
00150   inline const char*     next_nominus();
00151 
00152   // (*) unidentified flying objects -----------------------------------------
00153   inline std::vector<std::string>  unidentified_arguments(const std::vector<std::string>& Knowns) const;
00154   inline std::vector<std::string>  unidentified_options(const std::vector<std::string>& Knowns) const;
00155   inline std::vector<std::string>  unidentified_variables(const std::vector<std::string>& Knowns) const;
00156   inline std::vector<std::string>  unidentified_sections(const std::vector<std::string>& Knowns) const;
00157   inline std::vector<std::string>  unidentified_nominuses(const std::vector<std::string>& Knowns) const;
00158   
00159   inline std::string  unidentified_flags(const char* Known, 
00160                                          int ArgumentNumber /* =-1 */) const;
00161 #ifdef GETPOT_ALLOW_VARGS
00162   // TODO:    BAD USING VARGS
00163   inline std::vector<std::string>  unidentified_arguments(unsigned Number, const char* Known, ...) const;
00164   inline std::vector<std::string>  unidentified_options(unsigned Number, const char* Known, ...) const;
00165   inline std::vector<std::string>  unidentified_variables(unsigned Number, const char* Known, ...) const;
00166   inline std::vector<std::string>  unidentified_sections(unsigned Number, const char* Known, ...) const;
00167   inline std::vector<std::string>  unidentified_nominuses(unsigned Number, const char* Known, ...) const;
00168 #endif
00169 
00170   // (*) output --------------------------------------------------------------
00171   inline int print() const;
00172 
00173   private:
00174   // (*) Type Declaration ----------------------------------------------------
00175   struct variable {
00176     //-----------
00177     // Variable to be specified on the command line or in input files.
00178     // (i.e. of the form var='12 312 341')
00179 
00180     // -- constructors, destructors, assignment operator
00181     variable();
00182     variable(const variable&);
00183     variable(const char* Name, const char* Value);
00184     ~variable();
00185     variable& operator=(const variable& Other);
00186 
00187     void      take(const char* Value);
00188 
00189     // -- get a specific element in the string vector
00190     //    (return 0 if not present)
00191     const std::string*  get_element(unsigned Idx) const;
00192 
00193     // -- data memebers
00194     std::string         name;      // identifier of variable
00195     std::vector<std::string> value;     // value of variable stored in vector
00196     std::string         original;  // value of variable as given on command line
00197   };
00198 
00199   // (*) member variables --------------------------------------------------------------
00200   std::string          prefix;          // prefix automatically added in queries
00201   std::string          section;         // (for dollar bracket parsing)
00202   std::vector<std::string>  section_list;    // list of all parsed sections
00203   //     -- argurment vector 
00204   std::vector<std::string>  argv;            // vector of command line arguments stored as strings
00205   unsigned        cursor;          // cursor for argv
00206   bool            search_loop_f;   // shall search start at beginning after
00207   //                               // reaching end of arg array ?
00208   bool            search_failed_f; // flag indicating a failed search() operation
00209   //                               // (e.g. next() functions react with 'missed')
00210 
00211   //     --  nominus vector 
00212   int              nominus_cursor; // cursor for nominus_pointers
00213   std::vector<unsigned> idx_nominus;     // indecies of 'no minus' arguments
00214 
00215   //    -- intern variables 
00216   //       (arguments of the form "variable=value")
00217   std::vector<variable> variables; 
00218 
00219   // (*) helper functions ----------------------------------------------------
00220   //     -- produce three basic data vectors:
00221   //          - argument vector
00222   //          - nominus vector
00223   //          - variable dictionary
00224   inline void          __parse_argument_vector(const std::vector<std::string>& ARGV);
00225 
00226   //     -- helpers for argument list processing
00227   //        * search for a variable in 'variables' array
00228   inline const variable*  __find_variable(const char*) const;
00229   //        * support finding directly followed arguments
00230   inline const char*   __match_starting_string(const char* StartString);
00231   //        * support search for flags in a specific argument
00232   inline bool          __check_flags(const std::string& Str, const char* FlagList) const;
00233   //        * type conversion if possible     
00234   inline int      __convert_to_type(const std::string& String, int Default) const;
00235   inline double   __convert_to_type(const std::string& String, double Default) const;
00236   inline bool     __convert_to_type(const std::string& String, bool Default) const;
00237 
00238   //        * prefix extraction
00239   const std::string    __get_remaining_string(const std::string& String, const std::string& Start) const;
00240   //        * search for a specific string
00241   inline bool          __search_string_vector(const std::vector<std::string>& Vec, 
00242       const std::string& Str) const;    
00243 
00244   //     -- helpers to parse input files
00245   //        create an argument vector based on data found in an input file, i.e.:
00246   //           1) delete '#'-comments 
00247   //           2) contract assignment expressions, such as
00248   //                   my-variable   =    '007 J. B.'
00249   //             into 
00250   //                   my-variable='007 J. B.'
00251   //           3) interprete sections like '[../my-section]' etc.
00252   inline const std::string  __get_next_token(STD(istream)& istr);
00253   inline const std::string  __get_string(STD(istream)& istr);
00254   inline const std::string  __get_until_closing_bracket(STD(istream)& istr);
00255 
00256   inline std::string              __process_section_label(const std::string& Section, 
00257       std::vector<std::string>& section_stack);
00258 
00259   //      -- dollar bracket expressions
00260   std::string                   __DBE_expand_string(const std::string& str);
00261   std::string                   __DBE_expand(const std::string& str);
00262   const GetPot::variable*  __DBE_get_variable(const std::string& str);
00263   std::vector<std::string>           __DBE_get_expr_list(const std::string& str, const unsigned ExpectedNumber);
00264 
00265   std::string  __double2string(double Value) const { 
00266     char* tmp = new char[128];
00267     sprintf(tmp, "%e", Value);
00268     std::string result(tmp);
00269     delete [] tmp;
00270     return result;
00271   }
00272   std::string  __int2string(const int& Value) const { 
00273     char* tmp = new char[128];
00274     sprintf(tmp, "%i", Value);
00275     std::string result(tmp);
00276     delete [] tmp;
00277     return result;
00278   }
00279 };
00280 
00281 
00283 // (*) constructors, destructor, assignment operator
00284 //.............................................................................
00285 //
00286 inline void
00287 GetPot::__basic_initialization()
00288 {
00289   cursor = 0;              nominus_cursor = -1;
00290   search_failed_f = true;  search_loop_f = true;
00291   prefix = "";             section = "";      
00292 }
00293 
00294 
00295 
00296 inline 
00297 GetPot::GetPot()
00298 { __basic_initialization(); }
00299 
00300 
00301 
00302 inline 
00303 GetPot::GetPot(int argc_, char *argv_[])
00304 { 
00305   __basic_initialization();
00306 
00307   // -- make an internal copy of the argument list:
00308   std::vector<std::string> __argv;
00309   __argv.push_back(std::string(argv_[0]));
00310   for(int i=1; i<argc_; i++) {
00311     std::string tmp(argv_[i]);   // recall the problem with temporaries,
00312     __argv.push_back(tmp);  // reference counting in arguement lists ...
00313   }
00314   __parse_argument_vector(__argv); 
00315 }
00316 
00317 
00318 
00319 
00320 inline 
00321 GetPot::GetPot(const GetPot& Other)
00322 { GetPot::operator=(Other); }
00323 
00324 
00325 
00326 inline 
00327 GetPot::~GetPot()
00328 { }
00329 
00330 
00331 
00332 inline GetPot&
00333 GetPot::operator=(const GetPot& Other)
00334 {
00335   if (&Other != this) {
00336     argv            = Other.argv;
00337     variables       = Other.variables;
00338     cursor          = Other.cursor;
00339     nominus_cursor  = Other.nominus_cursor;
00340     search_failed_f = Other.search_failed_f;
00341     idx_nominus     = Other.idx_nominus;
00342     search_loop_f   = Other.search_loop_f;
00343   }
00344   return *this;
00345 }
00346 
00347 
00348 
00349 inline void
00350 GetPot::__parse_argument_vector(const std::vector<std::string>& ARGV)
00351 {
00352   // build internal databases:
00353   //   1) array with no-minus arguments (usually used as filenames)
00354   //   2) variable assignments:
00355   //             'variable name' '=' number | string
00356   section = "";
00357   std::vector<std::string>  section_stack;
00358   unsigned i=0;
00359   std::vector<std::string>::const_iterator it = ARGV.begin();
00360   argv.push_back(*it);
00361   for(it++; it != ARGV.end(); it++, i++) {
00362     std::string arg = *it;
00363     if( arg.length() == 0 ) continue;
00364 
00365     // -- [section] labels
00366     if( arg.length() > 1 && arg[0] == '[' && arg[arg.length()-1] == ']' ) {
00367       const std::string Name = __DBE_expand_string(arg.substr(1, arg.length()-2));
00368       section = __process_section_label(Name, section_stack);
00369       // new section --> append to list of sections
00370       if( std::find(section_list.begin(), section_list.end(), section) == section_list.end() )
00371         if( section.length() != 0 ) section_list.push_back(section);
00372       argv.push_back(arg);
00373     }
00374     else {
00375       arg = section + __DBE_expand_string(arg);
00376       argv.push_back(arg);
00377     }
00378 
00379     // -- separate array for nominus arguments
00380     if( arg[0] != '-' ) idx_nominus.push_back(unsigned(i));
00381 
00382     // -- variables: does arg contain a '=' operator ?
00383     for(const char* p = arg.c_str(); *p ; p++) {
00384       if( *p == '=' ) {
00385         // set terminating 'zero' to treat first part as single string
00386         // => arg (from start to 'p') = Name of variable
00387         //    p+1     (until terminating zero) = value of variable
00388         char* o = (char*)p++;
00389         *o = '\0';
00390         const GetPot::variable* Var = __find_variable(arg.c_str());
00391         if( Var == 0 ) variables.push_back(variable(arg.c_str(), p)); 
00392         else           ((GetPot::variable*)Var)->take(p);
00393         *o = '=';
00394         break;
00395       }
00396     }
00397   }
00398 }
00399 
00400 
00401 
00402 inline const std::string
00403 GetPot::__get_next_token(STD(istream)& istr)
00404   // get next concatinates string token. consider quotes that embrace
00405   // whitespaces
00406 {
00407   std::string token;
00408   int    tmp = 0; 
00409   int    last_letter = 0;
00410   while(1+1 == 2) {
00411     last_letter = tmp; tmp = istr.get();
00412     if( tmp == EOF 
00413         || ((tmp == ' ' || tmp == '\t' || tmp == '\n') && last_letter != '\\') ) {
00414       return token;
00415     }
00416     else if( tmp == '\'' && last_letter != '\\' ) {
00417       // QUOTES: un-backslashed quotes => it's a string
00418       token += __get_string(istr);
00419       continue;
00420     }
00421     else if( tmp == '{' && last_letter == '$') {
00422       token += '{' + __get_until_closing_bracket(istr);
00423       continue;
00424     }
00425     else if( tmp == '$' && last_letter == '\\') {
00426       token += tmp; tmp = 0;  //  so that last_letter will become = 0, not '$';
00427       continue;
00428     }
00429     else if( tmp == '\\' && last_letter != '\\') 
00430       continue;              // don't append un-backslashed backslashes
00431     token += tmp;
00432   }
00433 }
00434 
00435 
00436 
00437 inline const std::string
00438 GetPot::__get_string(STD(istream)& istr)
00439   // parse input until next matching '
00440 {
00441   std::string str;
00442   int    tmp = 0;
00443   int    last_letter = 0;
00444   while(1 + 1 == 2) {
00445     last_letter = tmp; tmp = istr.get();
00446     if( tmp == EOF)  return str;
00447     // un-backslashed quotes => it's the end of the string
00448     else if( tmp == '\'' && last_letter != '\\')  return str;
00449     else if( tmp == '\\' && last_letter != '\\')  continue; // don't append 
00450 
00451     str += tmp;
00452   }
00453 }
00454 
00455 
00456 
00457 inline const std::string
00458 GetPot::__get_until_closing_bracket(STD(istream)& istr)
00459   // parse input until next matching }
00460 {
00461   std::string str = ""; 
00462   int    tmp = 0;
00463   int    last_letter = 0;
00464   int    brackets = 1;
00465   while(1 + 1 == 2) {
00466     last_letter = tmp; tmp = istr.get();
00467     if( tmp == EOF) return str;
00468     else if( tmp == '{' && last_letter == '$') brackets += 1;
00469     else if( tmp == '}') {
00470       brackets -= 1;
00471       // un-backslashed brackets => it's the end of the string
00472       if( brackets == 0) return str + '}';
00473       else if( tmp == '\\' && last_letter != '\\') 
00474         continue;  // do not append an unbackslashed backslash
00475     }
00476     str += tmp;
00477   }
00478 }
00479 
00480 
00481 
00482 inline std::string
00483 GetPot::__process_section_label(const std::string& Section, 
00484     std::vector<std::string>& section_stack)
00485 {
00486   std::string sname = Section;
00487   //  1) subsection of actual section ('./' prefix)
00488   if( sname.length() >= 2 && sname.substr(0, 2) == "./" ) {
00489     sname = sname.substr(2);
00490   }
00491   //  2) subsection of parent section ('../' prefix)
00492   else if( sname.length() >= 3 && sname.substr(0, 3) == "../" ) {
00493     do {
00494       if( section_stack.end() != section_stack.begin() ) 
00495         section_stack.pop_back();
00496       sname = sname.substr(3);
00497     } while( sname.substr(0, 3) == "../" );
00498   }
00499   // 3) subsection of the root-section
00500   else {
00501     section_stack.erase(section_stack.begin(), section_stack.end());
00502     // [] => back to root section
00503   }
00504 
00505   if( sname != "" ) {
00506     // parse section name for 'slashes'
00507     unsigned i=0;
00508     while( i < sname.length() ) {
00509       if( sname[i] == '/' ) {
00510         section_stack.push_back(sname.substr(0,i));
00511         if( i+1 < sname.length()-1 )
00512           sname = sname.substr(i+1);
00513         i = 0;
00514       }
00515       else 
00516         i++;
00517     }      
00518     section_stack.push_back(sname);
00519   } 
00520   std::string section = "";
00521   if( section_stack.size() != 0 )
00522     victorate(std::string, section_stack, it) {
00523       section += *it + "/";
00524     }
00525   return section;
00526 }
00527 
00528 
00529 
00530 // convert string to DOUBLE, if not possible return Default
00531 inline double   
00532 GetPot::__convert_to_type(const std::string& String, double Default) const
00533 {
00534   double tmp;
00535   if( sscanf(String.c_str(),"%lf", &tmp) != 1 ) return Default;
00536   return tmp;
00537 }
00538 
00539 
00540 
00541 // convert string to INT, if not possible return Default
00542 inline int   
00543 GetPot::__convert_to_type(const std::string& String, int Default) const
00544 {
00545   int tmp;
00546   if( sscanf(String.c_str(),"%i", &tmp) != 1 ) return Default;
00547   return tmp;    
00548 }
00549 
00550 
00551 
00552 inline bool
00553 GetPot::__convert_to_type(const std::string& String, bool Default) const
00554 {
00555   std::string newstring(String);
00556   //std::transform(newstring.begin(), newstring.end(), newstring.begin(), std::toupper);
00557   for (unsigned int i=0; i<newstring.length(); ++i)
00558   {
00559     newstring[i]=toupper(newstring[i]);
00560   }
00561   
00562   if (newstring.find("TRUE")!=std::string::npos)  return true;
00563   if (newstring.find("FALSE")!=std::string::npos) return false;
00564   return Default;
00565 }
00566 
00567 
00568 
00570 // (*) cursor oriented functions
00571 //.............................................................................
00572 inline const std::string  
00573 GetPot::__get_remaining_string(const std::string& String, const std::string& Start) const
00574 // Checks if 'String' begins with 'Start' and returns the remaining String.
00575 // Returns None if String does not begin with Start.
00576 {
00577   if( Start == "" ) return String;
00578   // note: java.lang.String: substring(a,b) = from a to b-1
00579   //        C++ string:      substr(a,b)    = from a to a + b
00580   if( String.find(Start) == 0 ) return String.substr(Start.length());
00581   else                          return "";
00582 }
00583 
00584 
00585 
00586 //     -- search for a certain argument and set cursor to position
00587 inline bool
00588 GetPot::search(const std::string &Option)
00589 { 
00590   return search(Option.c_str());
00591 }
00592 
00593 
00594 
00595 inline bool
00596 GetPot::search(const char* Option)
00597 { 
00598   unsigned      OldCursor = cursor;
00599   const std::string  SearchTerm = prefix + Option;
00600 
00601   if( OldCursor >= argv.size() ) OldCursor = argv.size() - 1;
00602   search_failed_f = true;
00603 
00604   // (*) first loop from cursor position until end
00605   unsigned  c = cursor;
00606   for(; c < argv.size(); c++) {
00607     if( argv[c] == SearchTerm ) 
00608     { cursor = c; search_failed_f = false; return true; }
00609   }
00610   if( ! search_loop_f ) return false;
00611 
00612   // (*) second loop from 0 to old cursor position
00613   for(c = 1; c < OldCursor; c++) {
00614     if( argv[c] == SearchTerm ) 
00615     { cursor = c; search_failed_f = false; return true; }
00616   }
00617   // in case nothing is found the cursor stays where it was
00618   return false;
00619 }
00620 
00621 
00622 
00623 #ifdef GETPOT_ALLOW_VARGS
00624 inline bool
00625 GetPot::search(unsigned No, const char* P, ...)
00626 {
00627     if( No == 0 ) return false;
00628 
00629     // search for the first argument
00630     if( search(P) == true ) return true;
00631     
00632     // start interpreting variable argument list
00633     va_list ap;
00634     va_start(ap, P);
00635     for(unsigned i=1; i<No; i++) {
00636         char* Opt = va_arg(ap, char *);
00637         if( search(Opt) == true ) 
00638         { va_end(ap); return true; }
00639     }
00640     va_end(ap);
00641     return false;
00642 }
00643 #endif //GETPOT_ALLOW_VARGS
00644 
00645 
00646 
00647 inline void  
00648 GetPot::reset_cursor()
00649 { search_failed_f = false; cursor = 0; }
00650 
00651 
00652 
00653 inline void         
00654 GetPot::init_multiple_occurrence()
00655 { disable_loop(); reset_cursor(); }
00656 
00657 
00658 
00660 // (*) direct access to command line arguments
00661 //.............................................................................
00662 //
00663 inline const char*   
00664 GetPot::operator[](unsigned idx) const
00665 { return idx<argv.size() ? argv[idx].c_str() : 0; }
00666 
00667 
00668 
00669 inline int   
00670 GetPot::get(unsigned Idx, int Default) const
00671 { 
00672   if( Idx >= argv.size() ) return Default;
00673   return __convert_to_type(argv[Idx], Default);
00674 }
00675 
00676 
00677 
00678 inline double   
00679 GetPot::get(unsigned Idx, double Default) const
00680 { 
00681   if( Idx >= argv.size() ) return Default;
00682   return __convert_to_type(argv[Idx], Default);
00683 }
00684 
00685 
00686 
00687 inline const char*   
00688 GetPot::get(unsigned Idx, const char* Default) const
00689 { 
00690   if( Idx >= argv.size() ) return Default;
00691   else                     return argv[Idx].c_str();
00692 }
00693 
00694 
00695 
00696 inline unsigned 
00697 GetPot::size() const
00698 { return argv.size(); }
00699 //     -- next() function group
00700   inline int  
00701 GetPot::next(int Default)    
00702 { 
00703   if( search_failed_f ) return Default;
00704   cursor++; 
00705   if( cursor >= argv.size() ) 
00706   { cursor = argv.size(); return Default; }
00707 
00708   const std::string Remain = __get_remaining_string(argv[cursor], prefix);
00709 
00710   return Remain != "" ? __convert_to_type(Remain, Default) : Default;
00711 }
00712 
00713 
00714 
00715 inline double 
00716 GetPot::next(double Default) 
00717 { 
00718   if( search_failed_f ) return Default;
00719   cursor++;
00720 
00721   if( cursor >= argv.size() ) 
00722   { cursor = argv.size(); return Default; }
00723 
00724   std::string Remain = __get_remaining_string(argv[cursor], prefix);
00725 
00726   return Remain != "" ? __convert_to_type(Remain, Default) : Default;
00727 }
00728 
00729 
00730 
00731 inline const char*   
00732 GetPot::next(const char* Default) 
00733 { 
00734   if( search_failed_f ) return Default;
00735   cursor++; 
00736 
00737   if( cursor >= argv.size() )
00738   { cursor = argv.size(); return Default; }
00739 
00740   const std::string Remain = __get_remaining_string(argv[cursor], prefix);
00741 
00742   return Remain != "" ? Remain.c_str() : Default;
00743 }
00744 
00745 
00746 
00747 inline std::string
00748 GetPot::next(const std::string &Default) 
00749 { 
00750   if( search_failed_f ) return Default;
00751   cursor++; 
00752 
00753   if( cursor >= argv.size() )
00754   { cursor = argv.size(); return Default; }
00755 
00756   const std::string Remain = __get_remaining_string(argv[cursor], prefix);
00757 
00758   return Remain != "" ? Remain : Default;
00759 }
00760 
00761 
00762 
00763 //     -- follow() function group 
00764 //        distinct option to be searched for
00765 inline int 
00766 GetPot::follow(int Default, const char* Option) 
00767 { 
00768   if( search(Option) == false ) return Default;
00769   return next(Default);
00770 }
00771 
00772 
00773 
00774 inline double  
00775 GetPot::follow(double Default, const char* Option)
00776 { 
00777   if( search(Option) == false ) return Default;
00778   return next(Default);
00779 }
00780 
00781 
00782 
00783 inline const char* 
00784 GetPot::follow(const char* Default, const char* Option)
00785 { 
00786   if( search(Option) == false ) return Default;
00787   return next(Default);
00788 }
00789 
00790 
00791 
00792 #ifdef GETPOT_ALLOW_VARGS
00793   //     -- second follow() function group 
00794   //        multiple option to be searched for
00795   inline int 
00796   GetPot::follow(int Default, unsigned No, const char* P, ...) 
00797   { 
00798     if( No == 0 ) return Default;
00799     if( search(P) == true ) return next(Default);
00800   
00801     va_list ap;
00802     va_start(ap, P);
00803     for(unsigned i=1; i<No; i++) {
00804       char* Opt = va_arg(ap, char *);
00805       if( search(Opt) == true ) { 
00806         va_end(ap); 
00807         return next(Default); 
00808       }
00809     }
00810     va_end(ap); 
00811     return Default;
00812   }
00813 
00814 
00815 
00816   inline double  
00817   GetPot::follow(double Default, unsigned No, const char* P, ...)
00818   {
00819     if( No == 0 ) return Default;
00820     if( search(P) == true ) return next(Default);
00821   
00822     va_list ap;
00823     va_start(ap, P);
00824     for(unsigned i=1; i<No; i++) {
00825       char* Opt = va_arg(ap, char *);
00826       if( search(Opt) == true ) { 
00827         va_end(ap); 
00828         return next(Default); 
00829       }
00830     }
00831     va_end(ap); 
00832     return Default;
00833   }
00834 
00835 
00836 
00837   inline const char* 
00838   GetPot::follow(const char* Default, unsigned No, const char* P, ...)
00839   {
00840     if( No == 0 ) return Default;
00841     if( search(P) == true ) return next(Default);
00842   
00843     va_list ap;
00844     va_start(ap, P);
00845     for(unsigned i=1; i<No; i++) {
00846       char* Opt = va_arg(ap, char *);
00847       if( search(Opt) == true ) { 
00848         va_end(ap); 
00849         return next(Default); 
00850       }
00851     }
00852     va_end(ap); 
00853     return Default;
00854   }
00855 
00856 #endif // GETPOT_ALLOW_VARGS
00857 
00858 
00859 
00861 // (*) directly connected options
00862 //.............................................................................
00863 //
00864 inline int
00865 GetPot::direct_follow(int Default, const char* Option) 
00866 {
00867   const char* FollowStr = __match_starting_string(Option);
00868   if( FollowStr == 0 )                    return Default;
00869   if( ++cursor >= argv.size() ) cursor = argv.size();
00870   return __convert_to_type(FollowStr, Default);
00871 }
00872 
00873 
00874 
00875 inline double 
00876 GetPot::direct_follow(double Default, const char* Option) 
00877 {
00878   const char* FollowStr = __match_starting_string(Option);
00879   if( FollowStr == 0 )                   return Default;
00880   if( ++cursor >= argv.size() ) cursor = argv.size();
00881   return __convert_to_type(FollowStr, Default);
00882 }
00883 
00884 
00885 
00886 inline const char* 
00887 GetPot::direct_follow(const char* Default, const char* Option)
00888 {
00889   if( search_failed_f ) return Default;
00890   const char* FollowStr = __match_starting_string(Option);
00891   if( FollowStr == 0 )          return Default;
00892   if( ++cursor >= argv.size() ) cursor = argv.size();
00893   return FollowStr;
00894 }
00895 
00896 
00897 
00898 inline const char*
00899 GetPot::__match_starting_string(const char* StartString) 
00900   // pointer  to the place where the string after 
00901   //          the match inside the found argument starts.
00902   // 0        no argument matches the starting string.
00903 {
00904   const unsigned N = strlen(StartString);
00905   unsigned OldCursor = cursor;
00906   if( OldCursor >= argv.size() ) OldCursor = argv.size() - 1;
00907   search_failed_f = true;
00908 
00909   // (*) first loop from cursor position until end
00910   unsigned c = cursor;
00911   for(; c < argv.size(); c++) {
00912     if( strncmp(StartString, argv[c].c_str(), N) == 0)
00913     { cursor = c; search_failed_f = false; return &(argv[c].c_str()[N]); }
00914   }
00915 
00916   if( ! search_loop_f ) return false;
00917 
00918   // (*) second loop from 0 to old cursor position
00919   for(c = 1; c < OldCursor; c++) {
00920     if( strncmp(StartString, argv[c].c_str(), N) == 0)
00921     { cursor = c; search_failed_f = false; return &(argv[c].c_str()[N]); }
00922   }
00923   return 0;
00924 }
00925 
00926 
00927 
00929 // (*) search for flags
00930 //.............................................................................
00931 //
00932 inline bool
00933 GetPot::options_contain(const char* FlagList) const
00934 {
00935   // go through all arguments that start with a '-' (but not '--')
00936   std::string str;
00937   for(std::vector<std::string>::const_iterator it = argv.begin();
00938       it != argv.end();
00939       it++) {
00940     str = __get_remaining_string(*it, prefix);
00941 
00942     if( str.length() >= 2 && str[0] == '-' && str[1] != '-' )
00943       if( __check_flags(str, FlagList) ) return true;
00944   }
00945   return false;
00946 }
00947 
00948 
00949 
00950 inline bool
00951 GetPot::argument_contains(unsigned Idx, const char* FlagList) const
00952 {
00953   if( Idx >= argv.size() ) return false;
00954 
00955   if( prefix == "" )
00956     // search argument for any flag in flag list
00957     return __check_flags(argv[Idx], FlagList);
00958 
00959   // if a prefix is set, then the argument index is the index
00960   //   inside the 'namespace'
00961   // => only check list of arguments that start with prefix
00962   unsigned no_matches = 0;
00963   for(unsigned i=0; i<argv.size(); i++) {
00964     const std::string Remain = __get_remaining_string(argv[i], prefix);
00965     if( Remain != "") {
00966       no_matches += 1;
00967       if( no_matches == Idx)
00968         return __check_flags(Remain, FlagList);
00969     }
00970   }
00971   // no argument in this namespace
00972   return false;
00973 }
00974 
00975 
00976 
00977 inline bool
00978 GetPot::__check_flags(const std::string& Str, const char* FlagList) const
00979 {
00980   for(const char* p=FlagList; *p != '\0' ; p++)
00981     if( Str.find(*p) != std::string::npos ) return true; // found something
00982   return false;
00983 }
00984 
00985 
00986 
00988 // (*) nominus arguments
00989 inline std::vector<std::string>  
00990 GetPot::nominus_vector() const
00991 // return vector of nominus arguments
00992 {
00993   std::vector<std::string> nv;
00994   for(std::vector<unsigned>::const_iterator it = idx_nominus.begin();
00995       it != idx_nominus.end();
00996       it++) {
00997     nv.push_back(argv[*it]);
00998   }
00999   return nv;
01000 }
01001 
01002 
01003 
01004 inline const char* 
01005 GetPot::next_nominus()
01006 {
01007   if( nominus_cursor < int(idx_nominus.size()) - 1 )
01008     return argv[idx_nominus[++nominus_cursor]].c_str();
01009   return 0;
01010 }
01011 
01012 
01013 
01014 inline void 
01015 GetPot::reset_nominus_cursor()
01016 { nominus_cursor = -1; }
01017 
01018 
01019 
01021 // (*) variables
01022 //.............................................................................
01023 //
01024 inline bool
01025 GetPot::operator()(const char* VarName, bool Default) const
01026 {
01027   const variable* sv = __find_variable(VarName);
01028   if ( sv == 0 ) return Default;
01029   return __convert_to_type(sv->original, Default);
01030 }
01031 
01032 
01033 
01034 inline int 
01035 GetPot::operator()(const char* VarName, int Default) const
01036 {
01037   const variable*  sv = __find_variable(VarName);
01038   if( sv == 0 ) return Default;
01039   return __convert_to_type(sv->original, Default);
01040 }
01041 
01042 
01043 
01044 inline double
01045 GetPot::operator()(const char* VarName, double Default) const
01046 {
01047   const variable*  sv = __find_variable(VarName);
01048   if( sv == 0 ) return Default;
01049   return __convert_to_type(sv->original, Default);
01050 }
01051 
01052 
01053 
01054 inline const char*
01055 GetPot::operator()(const char* VarName, const char* Default) const
01056 {
01057   const variable*  sv = __find_variable(VarName);
01058   if( sv == 0 ) return Default;
01059   return sv->original.c_str();
01060 }
01061 
01062 
01063 
01064 inline std::string
01065 GetPot::operator()(const char* VarName, const std::string& Default) const
01066 {
01067   const variable*  sv = __find_variable(VarName);
01068   if( sv == 0 ) return Default;
01069   return sv->original;
01070 }
01071 
01072 
01073 
01074 inline int 
01075 GetPot::operator()(const char* VarName, int Default, unsigned Idx) const
01076 {
01077   const variable* sv = __find_variable(VarName);
01078   if( sv == 0 ) return Default;
01079   const std::string*  element = sv->get_element(Idx);
01080   if( element == 0 ) return Default;
01081   return __convert_to_type(*element, Default);
01082 }
01083 
01084 
01085 
01086 inline double
01087 GetPot::operator()(const char* VarName, double Default, unsigned Idx) const
01088 {
01089   const variable* sv = __find_variable(VarName);
01090   if( sv == 0 ) return Default;
01091   const std::string*  element = sv->get_element(Idx);
01092   if( element == 0 ) return Default;
01093   return __convert_to_type(*element, Default);
01094 }
01095 
01096 
01097 
01098 inline const char*
01099 GetPot::operator()(const char* VarName, const char* Default, unsigned Idx) const
01100 {
01101   const variable*  sv = __find_variable(VarName);
01102   if( sv == 0 ) return Default;
01103   const std::string* element = sv->get_element(Idx);     
01104   if( element == 0 )  return Default;
01105   return element->c_str();
01106 }
01107 
01108 
01109 
01110 inline unsigned
01111 GetPot::vector_variable_size(const char* VarName) const
01112 {
01113   const variable*  sv = __find_variable(VarName);
01114   if( sv == 0 ) return 0;
01115   return sv->value.size();
01116 }
01117 
01118 
01119 
01120 inline std::vector<std::string>
01121 GetPot::get_variable_names() const
01122 {
01123   std::vector<std::string>  result;
01124   for(std::vector<GetPot::variable>::const_iterator it = variables.begin();
01125       it != variables.end(); it++) {
01126     const std::string Tmp = __get_remaining_string((*it).name, prefix);
01127     if( Tmp != "" ) result.push_back(Tmp);
01128   }
01129   return result;
01130 }
01131 
01132 
01133 
01134 inline std::vector<std::string>
01135 GetPot::get_section_names() const
01136 { return section_list; }
01137 
01138 inline const GetPot::variable*
01139 GetPot::__find_variable(const char* Name) const
01140 {
01141   std::string name = prefix + Name;
01142   for(std::vector<variable>::const_iterator it = variables.begin();
01143       it != variables.end();
01144       it++)
01145     if( (*it).name == name ) return &(*it);
01146   return 0;
01147 }
01148 
01149 
01150 
01152 // (*) ouput (basically for debugging reasons
01153 //.............................................................................
01154 //
01155 inline int 
01156 GetPot::print() const
01157 {
01158   STD(cout) << "argc = " << argv.size() << STD(endl);
01159   for(std::vector<std::string>::const_iterator it = argv.begin(); it != argv.end(); it++)
01160     STD(cout) << *it << STD(endl);
01161   STD(cout) << STD(endl);
01162   return 1;
01163 }
01164 
01165 
01166 
01167 // (*) dollar bracket expressions (DBEs) ------------------------------------
01168 //
01169 //     1) Entry Function: __DBE_expand_string()
01170 //        Takes a string such as
01171 //
01172 //          "${+ ${x} ${y}}   Subject-${& ${section} ${subsection}}:   ${title}"
01173 //
01174 //        calls __DBE_expand() for each of the expressions
01175 //
01176 //           ${+ ${x} ${y}}
01177 //           ${& ${section} ${subsection}}
01178 //           ${Title}
01179 //
01180 //        and returns the string
01181 //
01182 //          "4711 Subject-1.01:   Mit den Clowns kamen die Schwaene"
01183 //
01184 //        assuming that
01185 //            x          = "4699"
01186 //            y          = "12"
01187 //            section    = "1."
01188 //            subsection = "01"
01189 //            title      = "Mit den Clowns kamen die Schwaene"
01190 //
01191 //      2) __DBE_expand():
01192 //
01193 //           checks for the command, i.e. the 'sign' that follows '${'
01194 //           divides the argument list into sub-expressions using
01195 //           __DBE_get_expr_list()
01196 //
01197 //           ${+ ${x} ${y}}                 -> "${x}"  "${y}"
01198 //           ${& ${section} ${subsection}}  -> "${section}" "${subsection}"
01199 //           ${Title}                       -> Nothing, variable expansion
01200 //
01201 //      3) __DBE_expression_list():
01202 //
01203 //           builds a vector of unbracketed whitespace separated strings, i.e.
01204 //
01205 //           "  ${Number}.a ${: Das Marmorbild} AB-${& Author= ${Eichendorf}-1870}"
01206 //
01207 //           is split into a vector
01208 //
01209 //              [0] ${Number}.a
01210 //              [1] ${: Das Marmorbild}
01211 //              [2] AB-${& Author= ${Eichendorf}}-1870
01212 //
01213 //           Each sub-expression is expanded using expand(). 
01214 //---------------------------------------------------------------------------    
01215 inline std::string 
01216 GetPot::__DBE_expand_string(const std::string& str) 
01217 {
01218   // Parses for closing operators '${ }' and expands them letting
01219   // white spaces and other letters as they are.
01220   std::string   new_string = "";
01221   unsigned open_brackets = 0;
01222   unsigned first = 0;
01223   for(unsigned i = 0;  i<str.size(); i++) {
01224     if( i < str.size() - 2 && str.substr(i, 2) == "${" ) {
01225       if( open_brackets == 0 ) first = i+2;
01226       open_brackets++;
01227     }
01228     else if( str[i] == '}' && open_brackets > 0) {
01229       open_brackets -= 1;
01230       if( open_brackets == 0 ) {
01231         const std::string Replacement = __DBE_expand(str.substr(first, i - first));
01232         new_string += Replacement;
01233       }
01234     }
01235     else if( open_brackets == 0 )
01236       new_string += str[i];
01237   }
01238   return new_string;
01239 }
01240 
01241 
01242 
01243 inline std::vector<std::string>
01244 GetPot::__DBE_get_expr_list(const std::string& str_, const unsigned ExpectedNumber)
01245   // ensures that the resulting vector has the expected number
01246   // of arguments, but they may contain an error message
01247 {
01248   std::string str = str_;
01249   // Separates expressions by non-bracketed whitespaces, expands them
01250   // and puts them into a list.
01251 
01252   unsigned i=0;
01253   // (1) eat initial whitespaces
01254   for(; i < str.size(); i++)
01255     if( ! isspace(str[i]) ) break;
01256 
01257   std::vector<std::string>   expr_list;
01258   unsigned         open_brackets = 0;
01259   std::vector<unsigned> start_idx;
01260   unsigned         start_new_string = i;
01261   unsigned         l = str.size();
01262 
01263   // (2) search for ${ } expressions ...
01264   while( i < l ) {
01265     const char letter = str[i];
01266     // whitespace -> end of expression
01267     if( isspace(letter) && open_brackets == 0) {
01268       expr_list.push_back(str.substr(start_new_string, i - start_new_string));
01269       bool no_breakout_f = true;
01270       for(i++; i < l ; i++) {
01271         if( ! isspace(str[i]) ) 
01272         { no_breakout_f = false; start_new_string = i; break; }
01273       }
01274       if( no_breakout_f ) {
01275         // end of expression list
01276         if( expr_list.size() < ExpectedNumber ) {
01277           const std::string   pre_tmp("<< ${ }: missing arguments>>");
01278           std::vector<std::string> tmp(ExpectedNumber - expr_list.size(), pre_tmp); 
01279           expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
01280         }
01281         return expr_list;
01282       }
01283     }
01284 
01285     // dollar-bracket expression
01286     if( str.length() >= i+2 && str.substr(i, 2) == "${" ) {
01287       open_brackets++;
01288       start_idx.push_back(i+2);
01289     }
01290     else if( letter == '}' && open_brackets > 0) {
01291       unsigned start = start_idx[start_idx.size()-1];
01292       start_idx.pop_back();
01293       const std::string Replacement = __DBE_expand(str.substr(start, i-start));
01294       if( start  < 3)
01295         str = Replacement + str.substr(i+1);
01296       else
01297         str = str.substr(0, start-2) + Replacement + str.substr(i+1);
01298       l = str.size();              
01299       i = start + Replacement.size() - 3;
01300       open_brackets--;
01301     }
01302     i++;
01303   }
01304 
01305   // end of expression list
01306   expr_list.push_back(str.substr(start_new_string, i-start_new_string));
01307 
01308   if( expr_list.size() < ExpectedNumber ) {
01309     const std::string   pre_tmp("<< ${ }: missing arguments>>");
01310     std::vector<std::string> tmp(ExpectedNumber - expr_list.size(), pre_tmp); 
01311     expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
01312   }
01313 
01314   return expr_list;
01315 }
01316 
01317 
01318 
01319 inline const GetPot::variable*
01320 GetPot::__DBE_get_variable(const std::string& VarName)
01321 {
01322   static GetPot::variable ev;
01323   std::string secure_Prefix = prefix;
01324 
01325   prefix = section;
01326   // (1) first search in currently active section
01327   const GetPot::variable* var = __find_variable(VarName.c_str());
01328   if( var != 0 ) { prefix = secure_Prefix; return var; }
01329 
01330   // (2) search in root name space
01331   prefix = "";
01332   var = __find_variable(VarName.c_str());
01333   if( var != 0 ) { prefix = secure_Prefix; return var; }
01334 
01335   prefix = secure_Prefix;
01336 
01337   // error occured => variable name == ""
01338   char* tmp = new char[VarName.length() + 25];
01339   sprintf(tmp, "<<${ } variable '%s' undefined>>", VarName.c_str());
01340   ev.name = "";
01341   ev.original = std::string(tmp);
01342   delete [] tmp;
01343   return &ev;
01344 }
01345 
01346   inline std::string 
01347 GetPot::__DBE_expand(const std::string& expr)
01348 {
01349   // ${: } pure text
01350   if( expr[0] == ':' )
01351     return expr.substr(1);
01352 
01353   // ${& expr expr ... } text concatination
01354   else if( expr[0] == '&' ) {
01355     const std::vector<std::string> A = __DBE_get_expr_list(expr.substr(1), 1);
01356 
01357     std::vector<std::string>::const_iterator it = A.begin();
01358     std::string result = *it++;
01359     for(; it != A.end(); it++) result += *it;
01360 
01361     return result;
01362   }
01363 
01364   // ${<-> expr expr expr} text replacement
01365   else if( expr.length() >= 3 && expr.substr(0, 3) == "<->" ) {
01366     std::vector<std::string> A = __DBE_get_expr_list(expr.substr(3), 3);
01367     unsigned tmp = 0;
01368     const unsigned L = A[1].length();
01369     while( (tmp = A[0].find(A[1])) != std::string::npos ) {
01370       A[0].replace(tmp, L, A[2]);
01371     }
01372     return A[0];
01373   }
01374   // ${+ ...}, ${- ...}, ${* ...}, ${/ ...} expressions
01375   else if( expr[0] == '+' ) {
01376     std::vector<std::string> A = __DBE_get_expr_list(expr.substr(1), 2);
01377     std::vector<std::string>::const_iterator it = A.begin();
01378     double result = __convert_to_type(*it++, 0.0);
01379     for(; it != A.end(); it++)
01380       result += __convert_to_type(*it, 0.0);
01381 
01382     return __double2string(result);
01383   }
01384   else if( expr[0] == '-' ) {
01385     std::vector<std::string> A = __DBE_get_expr_list(expr.substr(1), 2);
01386     std::vector<std::string>::const_iterator it = A.begin();
01387     double result = __convert_to_type(*it++, 0.0);
01388     for(; it != A.end(); it++)
01389       result -= __convert_to_type(*it, 0.0);
01390 
01391     return __double2string(result);
01392   }
01393   else if( expr[0] == '*' ) {
01394     std::vector<std::string> A = __DBE_get_expr_list(expr.substr(1), 2);
01395     std::vector<std::string>::const_iterator it = A.begin();
01396     double result = __convert_to_type(*it++, 0.0);
01397     for(; it != A.end(); it++)
01398       result *= __convert_to_type(*it, 0.0);
01399 
01400     return __double2string(result);
01401   }
01402   else if( expr[0] == '/' ) {
01403     std::vector<std::string> A = __DBE_get_expr_list(expr.substr(1), 2);
01404     std::vector<std::string>::const_iterator it = A.begin();
01405     double result = __convert_to_type(*it++, 0.0);
01406     if( result == 0 ) return "0.0";
01407     for(it++; it != A.end(); it++) {
01408       const double Q = __convert_to_type(*it, 0.0);
01409       if( Q == 0.0 ) return "0.0";          
01410       result /= Q;
01411     }
01412     return __double2string(result);
01413   }
01414 
01415   // ${^ ... } power expressions
01416   else if( expr[0] == '^' ) {
01417     std::vector<std::string> A = __DBE_get_expr_list(expr.substr(1), 2);
01418     std::vector<std::string>::const_iterator it = A.begin();
01419     double result = __convert_to_type(*it++, 0.0);
01420     for(; it != A.end(); it++)
01421       result = pow(result, __convert_to_type(*it, 0.0));
01422     return __double2string(result);
01423   }
01424 
01425   // ${==  } ${<=  } ${>= } comparisons (return the number of the first 'match'
01426   else if( expr.length() >= 2 && 
01427       ( expr.substr(0,2) == "==" || expr.substr(0,2) == ">=" || 
01428         expr.substr(0,2) == "<=" || expr[0] == '>'           || expr[0] == '<')) {
01429     // differentiate between two and one sign operators
01430     unsigned op = 0;
01431     enum { EQ, GEQ, LEQ, GT, LT };
01432     if      ( expr.substr(0, 2) == "==" ) op = EQ;
01433     else if ( expr.substr(0, 2) == ">=" ) op = GEQ;
01434     else if ( expr.substr(0, 2) == "<=" ) op = LEQ;
01435     else if ( expr[0] == '>' )            op = GT;
01436     else    /*                     "<" */ op = LT;
01437 
01438     std::vector<std::string> a;
01439     if ( op == GT || op == LT ) a = __DBE_get_expr_list(expr.substr(1), 2);
01440     else                        a = __DBE_get_expr_list(expr.substr(2), 2);
01441 
01442     std::string   x_orig = a[0];          
01443     double   x = __convert_to_type(x_orig, 1e37);
01444     unsigned i = 1;
01445 
01446     std::vector<std::string>::const_iterator y_orig = a.begin();
01447     for(y_orig++; y_orig != a.end(); y_orig++) { 
01448       double y = __convert_to_type(*y_orig, 1e37);
01449 
01450       // set the strings as reference if one wasn't a number
01451       if ( x == 1e37 || y == 1e37 ) {
01452         // it's a string comparison
01453         if( (op == EQ  && x_orig == *y_orig) || (op == GEQ && x_orig >= *y_orig) ||
01454             (op == LEQ && x_orig <= *y_orig) || (op == GT  && x_orig >  *y_orig) ||
01455             (op == LT  && x_orig <  *y_orig) )
01456           return __int2string(i);
01457       }
01458       else {
01459         // it's a number comparison
01460         if( (op == EQ  && x == y) || (op == GEQ && x >= y) ||
01461             (op == LEQ && x <= y) || (op == GT  && x >  y) || 
01462             (op == LT  && x <  y) )
01463           return __int2string(i);
01464       }
01465       i++;
01466     }
01467 
01468     // nothing fulfills the condition => return 0
01469     return "0";
01470   }
01471   // ${?? expr expr} select 
01472   else if( expr.length() >= 2 && expr.substr(0, 2) == "??" ) {
01473     std::vector<std::string> a = __DBE_get_expr_list(expr.substr(2), 2);
01474     double x = __convert_to_type(a[0], 1e37);
01475     // last element is always the default argument
01476     if( x == 1e37 || x < 0 || x >= a.size() - 1 ) return a[a.size()-1];
01477 
01478     // round x to closest integer
01479     return a[int(x+0.5)];
01480   }
01481   // ${? expr expr expr} if then else conditions
01482   else if( expr[0] == '?' ) {
01483     std::vector<std::string> a = __DBE_get_expr_list(expr.substr(1), 2);
01484     if( __convert_to_type(a[0], 0.0) == 1.0 ) return a[1];
01485     else if( a.size() > 2 )     return a[2];
01486   }
01487   // ${! expr} maxro expansion 
01488   else if( expr[0] == '!' ) {
01489     const GetPot::variable* Var = __DBE_get_variable(expr.substr(1));
01490     // error
01491     if( Var->name == "" ) return std::string(Var->original);
01492 
01493     const std::vector<std::string> A = __DBE_get_expr_list(Var->original, 2);
01494     return A[0];
01495   }
01496   // ${@: } - string subscription
01497   else if( expr.length() >= 2 && expr.substr(0,2) == "@:" ) {
01498     const std::vector<std::string> A = __DBE_get_expr_list(expr.substr(2), 2);
01499     double x = __convert_to_type(A[1], 1e37);
01500 
01501     // last element is always the default argument
01502     if( x == 1e37 || x < 0 || x >= A[0].size() - 1)
01503       return "<<1st index out of range>>";
01504 
01505     if( A.size() > 2 ) {
01506       double y = __convert_to_type(A[2], 1e37);
01507       if ( y != 1e37 && y > 0 && y <= A[0].size() - 1 && y > x )
01508         return A[0].substr(int(x+0.5), int(y+1.5) - int(x+0.5));
01509       else if( y == -1 )
01510         return A[0].substr(int(x+0.5));
01511       return "<<2nd index out of range>>";
01512     }
01513     else {
01514       char* tmp = new char[2];
01515       tmp[0] = A[0][int(x+0.5)]; tmp[1] = '\0';
01516       std::string result(tmp);
01517       delete [] tmp;
01518       return result;
01519     }
01520   }
01521   // ${@ } - vector subscription
01522   else if( expr[0] == '@' ) {
01523     std::vector<std::string>          A   = __DBE_get_expr_list(expr.substr(1), 2);
01524     const GetPot::variable* Var = __DBE_get_variable(A[0]);
01525     // error
01526     if( Var->name == "" ) {    
01527       // make a copy of the string if an error occured
01528       // (since the error variable is a static variable inside get_variable())
01529       return std::string(Var->original);
01530     }
01531 
01532     double x = __convert_to_type(A[1], 1e37);
01533 
01534     // last element is always the default argument
01535     if (x == 1e37 || x < 0 || x >= Var->value.size() )
01536       return "<<1st index out of range>>";
01537 
01538     if ( A.size() > 2) {
01539       double y = __convert_to_type(A[2], 1e37);
01540       int    begin = int(x+0.5);
01541       int    end = 0;
01542       if ( y != 1e37 && y > 0 && y <= Var->value.size() && y > x)
01543         end = int(y+1.5);
01544       else if( y == -1 )
01545         end = Var->value.size();
01546       else
01547         return "<<2nd index out of range>>";                
01548 
01549       std::string result = *(Var->get_element(begin));
01550       for(int i = begin+1; i < end; i++) 
01551         result += std::string(" ") + *(Var->get_element(i));
01552       return result;
01553     }
01554     else
01555       return *(Var->get_element(int(x+0.5)));
01556   }
01557 
01558   const std::vector<std::string>    A = __DBE_get_expr_list(expr, 1);
01559   const GetPot::variable* B = __DBE_get_variable(A[0]);
01560 
01561   // make a copy of the string if an error occured
01562   // (since the error variable is a static variable inside get_variable())
01563   if( B->name == "" ) return std::string(B->original);
01564   else                return B->original;
01565 }
01566 
01567 
01568 
01570 // (*) unidentified flying objects
01571 //.............................................................................
01572 //
01573 inline bool
01574 GetPot::__search_string_vector(const std::vector<std::string>& VecStr, const std::string& Str) const
01575 {
01576   victorate(std::string, VecStr, itk) {
01577     if( *itk == Str ) return true;
01578   }
01579   return false;
01580 }
01581 
01582 #ifdef GETPOT_ALLOW_VARGS
01583   inline std::vector<std::string> 
01584   GetPot::unidentified_arguments(unsigned Number, 
01585       const char* KnownArgument1, ...) const
01586   {
01587     std::vector<std::string> known_arguments;
01588   
01589     // (1) create a vector of known arguments
01590     if( Number == 0 ) return std::vector<std::string>();
01591   
01592     va_list ap;
01593     va_start(ap, KnownArgument1);
01594     known_arguments.push_back(std::string(KnownArgument1));
01595     for(unsigned i=1; i<Number; i++)
01596       known_arguments.push_back(std::string(va_arg(ap, char *)));
01597     va_end(ap);
01598   
01599     return unidentified_arguments(known_arguments);
01600   }
01601   
01602   
01603   inline std::vector<std::string> 
01604   GetPot::unidentified_options(unsigned Number, 
01605       const char* KnownOption1, ...) const
01606   {
01607     std::vector<std::string> known_options;
01608   
01609     // (1) create a vector of known arguments
01610     if( Number == 0 ) return std::vector<std::string>();
01611   
01612     va_list ap;
01613     va_start(ap, KnownOption1);
01614     known_options.push_back(std::string(KnownOption1));
01615     for(unsigned i=1; i<Number; i++)
01616       known_options.push_back(std::string(va_arg(ap, char *)));
01617     va_end(ap);
01618   
01619     return unidentified_options(known_options);
01620   }
01621   
01622   inline std::vector<std::string> 
01623   GetPot::unidentified_variables(unsigned Number, 
01624     const char* KnownVariable1, ...) const
01625   {
01626     std::vector<std::string> known_variables;
01627   
01628     // create vector of known arguments
01629     if( Number == 0 ) return std::vector<std::string>();
01630   
01631     va_list ap;
01632     va_start(ap, KnownVariable1);
01633     known_variables.push_back(std::string(KnownVariable1));
01634     for(unsigned i=1; i<Number; i++)
01635       known_variables.push_back(std::string(va_arg(ap, char *)));
01636     va_end(ap);
01637   
01638     return unidentified_variables(known_variables);
01639   }
01640   
01641   inline std::vector<std::string> 
01642   GetPot::unidentified_sections(unsigned Number, 
01643       const char* KnownSection1, ...) const
01644   {
01645     std::vector<std::string> known_sections;
01646   
01647     // (1) create a vector of known arguments
01648     if( Number == 0 ) return std::vector<std::string>();
01649   
01650     va_list ap;
01651     va_start(ap, KnownSection1);
01652     known_sections.push_back(std::string(KnownSection1));
01653     for(unsigned i=1; i<Number; i++) {
01654       std::string tmp = std::string(va_arg(ap, char *));
01655       if( tmp.length() == 0 ) continue;
01656       if( tmp[tmp.length()-1] != '/' ) tmp += '/';
01657       known_sections.push_back(tmp);
01658     }
01659     va_end(ap);
01660   
01661     return unidentified_sections(known_sections);
01662   }
01663   
01664   inline std::vector<std::string> 
01665   GetPot::unidentified_nominuses(unsigned Number, const char* Known, ...) const
01666   {
01667     std::vector<std::string> known_nominuses;
01668   
01669     // create vector of known arguments
01670     if( Number == 0 ) return std::vector<std::string>();
01671   
01672     va_list ap;
01673     va_start(ap, Known);
01674     known_nominuses.push_back(std::string(Known));
01675     for(unsigned i=1; i<Number; i++) {
01676       std::string tmp = std::string(va_arg(ap, char *));
01677       if( tmp.length() == 0 ) continue;
01678       known_nominuses.push_back(tmp);
01679     }
01680     va_end(ap);
01681   
01682     return unidentified_nominuses(known_nominuses);
01683   }
01684   
01685 #endif //GETPOT_ALLOW_VARGS
01686 
01687 
01688 
01689 inline std::string
01690 GetPot::unidentified_flags(const char* KnownFlagList, int ArgumentNumber=-1) const
01691 // Two modes:
01692 //  ArgumentNumber >= 0 check specific argument 
01693 //  ArgumentNumber == -1 check all options starting with one '-' 
01694 //                       for flags
01695 {
01696   std::string         ufos;
01697   std::vector<std::string> known_arguments;
01698   std::string         KFL(KnownFlagList);
01699 
01700   // (2) iteration over '-' arguments (options)
01701   if( ArgumentNumber == -1 ) {
01702     std::vector<std::string>::const_iterator it = argv.begin();
01703     it++; // forget about argv[0] (application or filename)
01704     for(; it != argv.end(); it++) {
01705       // -- argument belongs to prefixed section ?
01706       const std::string arg = __get_remaining_string(*it, prefix);
01707       if( arg == "" ) continue;
01708 
01709       // -- does arguments start with '-' (but not '--')
01710       if     ( arg.length() < 2 ) continue;
01711       else if( arg[0] != '-' )    continue;
01712       else if( arg[1] == '-' )    continue;
01713 
01714       // -- check out if flags inside option are contained in KnownFlagList
01715       const char* p=arg.c_str();
01716       p++; // skip starting minus
01717       for(; *p != '\0' ; p++)
01718         if( KFL.find(*p) == std::string::npos ) ufos += *p;
01719     }
01720   }
01721   // (1) check specific argument
01722   else {
01723     // -- only check arguments that start with prefix
01724     int no_matches = 0;
01725     for(unsigned i=1; i<argv.size(); i++) {
01726       const std::string Remain = __get_remaining_string(argv[i], prefix);
01727       if( Remain != "") {
01728         no_matches++;
01729         if( no_matches == ArgumentNumber) {
01730           // -- the right argument number inside the section is found
01731           // => check it for flags
01732           const char* p = Remain.c_str();
01733           p++; // skip starting minus
01734           for(; *p != '\0' ; p++)
01735             if( KFL.find(*p) == std::string::npos ) ufos += *p;
01736           return ufos;
01737         }
01738       }
01739     }
01740   }
01741   return ufos;
01742 }
01743 
01744 
01745 
01746 inline std::vector<std::string> 
01747 GetPot::unidentified_arguments(const std::vector<std::string>& Knowns) const
01748 {
01749   std::vector<std::string> ufos;
01750   std::vector<std::string>::const_iterator it = argv.begin();
01751   it++; // forget about argv[0] (application or filename)
01752   for(; it != argv.end(); it++) {
01753     // -- argument belongs to prefixed section ?
01754     const std::string arg = __get_remaining_string(*it, prefix);
01755     if( arg == "" ) continue;
01756 
01757     // -- check if in list
01758     if( __search_string_vector(Knowns, arg) == false)
01759       ufos.push_back(*it);
01760   }
01761   return ufos;
01762 }
01763 
01764 
01765 
01766 inline std::vector<std::string> 
01767 GetPot::unidentified_options(const std::vector<std::string>& Knowns) const
01768 {
01769   std::vector<std::string> ufos;
01770   std::vector<std::string>::const_iterator it = argv.begin();
01771   it++; // forget about argv[0] (application or filename)
01772   for(; it != argv.end(); it++) {
01773     // -- argument belongs to prefixed section ?
01774     const std::string arg = __get_remaining_string(*it, prefix);
01775     if( arg == "" ) continue;
01776 
01777     // is argument really an option (starting with '-') ?
01778     if( arg.length() < 1 || arg[0] != '-' ) continue;
01779 
01780     if( __search_string_vector(Knowns, arg) == false)
01781       ufos.push_back(*it);
01782   }
01783 
01784   return ufos;
01785 }
01786 
01787 
01788 
01789 inline std::vector<std::string> 
01790 GetPot::unidentified_variables(const std::vector<std::string>& Knowns) const
01791 {
01792   std::vector<std::string> ufos;
01793 
01794   victorate(GetPot::variable, variables, it) {
01795     // -- check if variable has specific prefix
01796     const std::string var_name = __get_remaining_string((*it).name, prefix);
01797     if( var_name == "" ) continue;
01798 
01799     // -- check if variable is known
01800     if( __search_string_vector(Knowns, var_name) == false)
01801       ufos.push_back((*it).name);
01802   }
01803   return ufos;    
01804 }
01805 
01806 
01807 
01808 inline std::vector<std::string> 
01809 GetPot::unidentified_sections(const std::vector<std::string>& Knowns) const
01810 {
01811   std::vector<std::string> ufos;
01812 
01813   victorate(std::string, section_list, it) {
01814     // -- check if section conform to prefix
01815     const std::string sec_name = __get_remaining_string(*it, prefix);
01816     if( sec_name == "" ) continue;
01817 
01818     // -- check if section is known
01819     if( __search_string_vector(Knowns, sec_name) == false )
01820       ufos.push_back(*it);
01821   }
01822 
01823   return ufos;    
01824 }
01825 
01826 
01827 
01828 inline std::vector<std::string> 
01829 GetPot::unidentified_nominuses(const std::vector<std::string>& Knowns) const
01830 {
01831   std::vector<std::string> ufos;
01832 
01833   // (2) iterate over all arguments 
01834   std::vector<std::string>::const_iterator it = argv.begin();
01835   it++; // forget about argv[0] (application or filename)
01836   for(; it != argv.end(); it++) {
01837     // -- check if nominus part of prefix
01838     const std::string arg = __get_remaining_string(*it, prefix);
01839     if( arg == "" ) continue;
01840 
01841     if( arg.length() < 1 )                                  continue;
01842     // option ? --> not a nomius 
01843     if( arg[0] == '-' )                                     continue;
01844     // section ? --> not a real nominus
01845     if( arg[0] == '[' && arg[arg.length()-1] == ']' ) continue;
01846     // variable definition ? --> not a real nominus
01847     bool continue_f = false;
01848     for(unsigned i=0; i<arg.length() ; i++)
01849       if( arg[i] == '=' ) { continue_f = true; break; }
01850     if( continue_f )                                           continue;
01851 
01852     // real nominuses are compared with the given list
01853     if( __search_string_vector(Knowns, arg) == false )
01854       ufos.push_back(*it);
01855   }    
01856   return ufos;
01857 }
01858 
01859 
01860 
01862 // (*) variable class
01863 //.............................................................................
01864 //
01865 inline
01866 GetPot::variable::variable()
01867 {}
01868 
01869 
01870 
01871 inline
01872 GetPot::variable::variable(const variable& Other)
01873 { 
01874 #ifdef WIN32
01875   operator=(Other); 
01876 #else
01877   GetPot::variable::operator=(Other); 
01878 #endif
01879 }
01880 
01881 
01882 
01883 inline
01884 GetPot::variable::variable(const char* Name, const char* Value)
01885 : name(Name) 
01886 { 
01887   // make a copy of the 'Value'
01888   take(Value);
01889 }
01890 
01891 
01892 
01893 inline const std::string*
01894 GetPot::variable::get_element(unsigned Idx) const
01895 { if( Idx >= value.size() ) return 0; else return &(value[Idx]); }
01896 
01897 
01898 
01899 inline void
01900 GetPot::variable::take(const char* Value)
01901 { 
01902   original = std::string(Value);
01903 
01904   // separate string by white space delimiters using 'strtok'
01905   // thread safe usage of strtok (no static members)
01906   char* spt = 0; 
01907   // make a copy of the 'Value'
01908   char* copy = new char[strlen(Value)+1];
01909   strcpy(copy, Value);
01910   char* follow_token = strtok_r(copy, " \t\n", &spt);
01911   if( value.size() != 0 ) value.erase(value.begin(), value.end());
01912   while(follow_token != 0) {
01913     value.push_back(std::string(follow_token));
01914     follow_token = strtok_r(NULL, " \t\n", &spt);
01915   }
01916 
01917   delete [] copy;
01918 }
01919 
01920 
01921 
01922 inline
01923 GetPot::variable::~variable()
01924 {}
01925 
01926 
01927 
01928 inline GetPot::variable& 
01929 GetPot::variable::operator=(const GetPot::variable& Other)
01930 {
01931   if( &Other != this) {
01932     name     = Other.name;
01933     value    = Other.value;
01934     original = Other.original;
01935   }
01936   return *this;
01937 }
01938 
01939 
01940 //using namespace __GetPot_namespace__;
01941 
01942 #undef victorate
01943 #undef reduce
01944 #endif // __GETPOT_H__
01945 
01946 



Project Hosted By:
SourceForge.net Logo