Home Hierarchy Members Alphabetical Related Pages

argstream.h

Go to the documentation of this file.
00001 /* Copyright (C) 2004 Xavier Décoret <Xavier.Decoret@imag.fr>
00002  *
00003  * argsteam is free software; you can redistribute it and/or modify
00004  * it under the terms of the GNU General Public License as published by
00005  * the Free Software Foundation; either version 2 of the License, or
00006  * (at your option) any later version.
00007  * 
00008  * Foobar is distributed in the hope that it will be useful,
00009  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  * GNU General Public License for more details.
00012  * 
00013  * You should have received a copy of the GNU General Public License
00014  * along with Foobar; if not, write to the Free Software
00015  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
00016  */
00017 
00018 #ifndef ARGSTREAM_H
00019 #define ARGSTREAM_H
00020 
00021 
00022 #include <string>
00023 #include <list>
00024 #include <deque>
00025 #include <map>
00026 #include <stdexcept>
00027 #include <sstream>
00028 #include <iostream> 
00029 
00030 namespace 
00031 {
00032   class argstream;
00033 
00034   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00035   // Interface of ValueHolder<T>
00036   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00037   template<class T>
00038   class ValueHolder;
00039   
00040   template <class T>
00041   argstream& operator>> (argstream&, const ValueHolder<T>&);
00042 
00043   template<class T>
00044   class ValueHolder
00045   {
00046   public:
00047     ValueHolder(char s,
00048                                                                 const char* l,
00049                                                                 T& b,
00050                                                                 const char* desc,
00051                                                                 bool mandatory);
00052     ValueHolder(const char* l,
00053                                                                 T& b,
00054                                                                 const char* desc,
00055                                                                 bool mandatory);
00056     ValueHolder(char s,
00057                                                                 T& b,
00058                                                                 const char* desc,
00059                                                                 bool mandatory);
00060     friend argstream& operator>><>(argstream& s,const ValueHolder<T>& v);
00061     std::string name() const;
00062     std::string description() const;
00063   private:
00064     std::string shortName_;
00065     std::string longName_;
00066     T*          value_;
00067     T           initialValue_;
00068     std::string description_;  
00069     bool        mandatory_;
00070   };
00071   template <class T>
00072   inline ValueHolder<T>
00073   parameter(char s,
00074                                                 const char* l,
00075                                                 T& b,
00076                                                 const char* desc="",
00077                                                 bool mandatory = true)
00078   {
00079     return ValueHolder<T>(s,l,b,desc,mandatory);
00080   }
00081   template <class T>
00082   inline ValueHolder<T>
00083   parameter(char s,
00084                                                 T& b,
00085                                                 const char* desc="",
00086                                                 bool mandatory = true)
00087   {
00088     return ValueHolder<T>(s,b,desc,mandatory);
00089   }
00090   template <class T>
00091   inline ValueHolder<T>
00092   parameter(const char* l,
00093                                                 T& b,
00094                                                 const char* desc="",
00095                                                 bool mandatory = true)
00096   {
00097     return ValueHolder<T>(l,b,desc,mandatory);
00098   }
00099   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00100   // Interface of OptionHolder
00101   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00102   class OptionHolder
00103   {
00104   public:
00105     inline OptionHolder(char s,
00106                                                                                                 const char* l,
00107                                                                                                 bool& b,
00108                                                                                                 const char* desc);
00109     inline OptionHolder(const char* l,
00110                                                                                                 bool& b,
00111                                                                                                 const char* desc);
00112     inline OptionHolder(char s,
00113                                                                                                 bool& b,
00114                                                                                                 const char* desc);
00115     friend argstream& operator>>(argstream& s,const OptionHolder& v);
00116     inline std::string name() const;
00117     inline std::string description() const;
00118   protected:
00119     inline OptionHolder(char s,
00120                                                                                                 const char* l,
00121                                                                                                 const char* desc);  
00122     friend OptionHolder help(char s='h',
00123                                                                                                                  const char* l="help",
00124                                                                                                                  const char* desc="Display this help");
00125   private:
00126     std::string shortName_;
00127     std::string longName_;
00128     bool*       value_;
00129     std::string description_;  
00130   };
00131   inline OptionHolder
00132   option(char s,
00133                                  const char* l,
00134                                  bool& b,
00135                                  const char* desc="")
00136   {
00137     return OptionHolder(s,l,b,desc);
00138   }
00139   inline OptionHolder
00140   option(char s,
00141                                  bool& b,
00142                                  const char* desc="")
00143   {
00144     return OptionHolder(s,b,desc);
00145   }
00146   inline OptionHolder
00147   option(const char* l,
00148                                  bool& b,
00149                                  const char* desc="")
00150   {
00151     return OptionHolder(l,b,desc);
00152   }
00153   inline OptionHolder
00154   help(char s,
00155        const char* l,
00156        const char* desc)
00157   {
00158     return OptionHolder(s,l,desc);
00159   }
00160   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00161   // Interface of ValuesHolder
00162   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00163   template<class T,class O>
00164   class ValuesHolder;
00165 
00166   template <class T,class O>
00167   argstream& operator>>(argstream&, const ValuesHolder<T,O>&);
00168         
00169   template<class T,class O>
00170   class ValuesHolder
00171   {
00172   public:
00173     ValuesHolder(const O& o,
00174                                                                  const char* desc,
00175                                                                  int len);
00176     friend argstream& operator>><>(argstream& s,const ValuesHolder<T,O>& v);
00177     std::string name() const;
00178     std::string description() const;
00179     typedef T value_type;
00180   private:
00181     mutable O   value_;
00182     std::string description_;  
00183     int         len_;
00184     char        letter_;
00185   };
00186   template<class T,class O>
00187   inline ValuesHolder<T,O>
00188   values(const O& o,
00189                                  const char* desc="",
00190                                  int len=-1)
00191   {
00192     return ValuesHolder<T,O>(o,desc,len);
00193   }
00194   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00195   // Interface of ValueParser
00196   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00197   template <class T>
00198   class ValueParser
00199   {
00200   public:
00201     inline T operator()(const std::string& s) const
00202       {
00203                                 std::istringstream is(s);
00204                                 T t;
00205                                 is>>t;
00206                                 return t;
00207       }
00208   };
00209   // We need to specialize for string otherwise parsing of a value that
00210   // contains space (for example a string with space passed in quotes on the
00211   // command line) would parse only the first element of the value!!!
00212   template <>
00213   class ValueParser<std::string>
00214   {
00215   public:
00216     inline std::string operator()(const std::string& s) const
00217       {
00218                                 return s;
00219       }
00220   };  
00221   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00222   // Interface of argstream
00223   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00224   class argstream
00225   {
00226   public:
00227     inline argstream(int argc,char** argv);
00228     inline argstream(const char* c);
00229     template<class T>
00230     friend argstream& operator>>(argstream& s,const ValueHolder<T>& v);
00231     friend inline argstream& operator>>(argstream& s,const OptionHolder& v);
00232     template<class T,class O>
00233     friend argstream& operator>>(argstream& s,const ValuesHolder<T,O>& v);
00234 
00235     inline bool helpRequested() const;
00236     inline bool isOk() const;
00237     inline std::string errorLog() const;
00238     inline std::string usage() const;
00239     inline void defaultErrorHandling(bool ignoreUnused=false) const;
00240     static inline char uniqueLetter();
00241   protected:
00242     void parse(int argc,char** argv);
00243   private:
00244     typedef std::list<std::string>::iterator value_iterator;
00245     typedef std::pair<std::string,std::string> help_entry;
00246     std::string                          progName_;
00247     std::map<std::string,value_iterator> options_;
00248     std::list<std::string>               values_;
00249     bool                                 minusActive_;
00250     bool                                 isOk_;
00251     std::deque<help_entry>               argHelps_;
00252     std::string                          cmdLine_;
00253     std::deque<std::string>              errors_;
00254     bool                                 helpRequested_;
00255   };
00256   //************************************************************
00257   // Implementation of ValueHolder<T>
00258   //************************************************************
00259   template<class T>
00260   ValueHolder<T>::ValueHolder(char s,
00261                                                                                                                         const char* l,
00262                                                                                                                         T& v,
00263                                                                                                                         const char* desc,
00264                                                                                                                         bool mandatory)
00265     :  shortName_(1,s),
00266        longName_(l),
00267        value_(&v),
00268        initialValue_(v),
00269        description_(desc),
00270        mandatory_(mandatory)
00271   {
00272   }
00273   template<class T>
00274   ValueHolder<T>::ValueHolder(const char* l,
00275                                                                                                                         T& v,
00276                                                                                                                         const char* desc,
00277                                                                                                                         bool mandatory)
00278     :  longName_(l),
00279        value_(&v),
00280        initialValue_(v),
00281        description_(desc),
00282        mandatory_(mandatory)
00283   {
00284   }
00285   template<class T>
00286   ValueHolder<T>::ValueHolder(char s,
00287                                                                                                                         T& v,
00288                                                                                                                         const char* desc,
00289                                                                                                                         bool mandatory)
00290     :  shortName_(1,s),
00291        value_(&v),
00292        initialValue_(v),
00293        description_(desc),
00294        mandatory_(mandatory)
00295   {
00296   }
00297   template<class T>
00298   std::string
00299   ValueHolder<T>::name() const
00300   {
00301     std::ostringstream  os;
00302     if (!shortName_.empty()) os<<'-'<<shortName_;
00303     if (!longName_.empty()) {      
00304       if (!shortName_.empty()) os<<'/';
00305       os<<"--"<<longName_;
00306     }
00307     return os.str();
00308   }
00309   template<class T>
00310   std::string
00311   ValueHolder<T>::description() const
00312   {
00313     std::ostringstream  os;  
00314     os<<description_;
00315     if (mandatory_)
00316     {
00317       os<<"(mandatory)";
00318     }
00319     else
00320     {
00321       os<<"(default="<<initialValue_<<")";
00322     }
00323     return os.str();
00324   }
00325   //************************************************************
00326   // Implementation of OptionHolder
00327   //************************************************************
00328   inline OptionHolder::OptionHolder(char s,
00329                                                                                                                                                 const char* l,
00330                                                                                                                                                 bool& b,
00331                                                                                                                                                 const char* desc)
00332     : shortName_(1,s),
00333       longName_(l),
00334       value_(&b),
00335       description_(desc)
00336   {
00337   }
00338   inline OptionHolder::OptionHolder(const char* l,
00339                                                                                                                                                 bool& b,
00340                                                                                                                                                 const char* desc)
00341     : longName_(l),
00342       value_(&b),
00343       description_(desc)
00344   {
00345   }
00346   inline OptionHolder::OptionHolder(char s,
00347                                                                                                                                                 bool& b,
00348                                                                                                                                                 const char* desc)
00349     : shortName_(1,s),
00350       value_(&b),
00351       description_(desc)
00352   {
00353   }
00354   inline OptionHolder::OptionHolder(char s,
00355                                                                                                                                                 const char* l,
00356                                                                                                                                                 const char* desc)
00357     : shortName_(1,s),
00358       longName_(l),
00359       value_(NULL),
00360       description_(desc)
00361   {
00362   }
00363   inline std::string
00364   OptionHolder::name() const
00365   {
00366     std::ostringstream  os;
00367     if (!shortName_.empty()) os<<'-'<<shortName_;
00368     if (!longName_.empty())
00369     {
00370       if (!shortName_.empty()) os<<'/';
00371       os<<"--"<<longName_;
00372     }
00373     return os.str();
00374   }
00375   inline std::string
00376   OptionHolder::description() const
00377   {
00378     return description_;
00379   }
00380   //************************************************************
00381   // Implementation of ValuesHolder<T,O>
00382   //************************************************************
00383   template<class T,class O>
00384   ValuesHolder<T,O>::ValuesHolder(const O& o,
00385                                                                                                                                         const char* desc,
00386                                                                                                                                         int len)
00387     : value_(o),
00388       description_(desc),
00389       len_(len)
00390   {
00391     letter_ = argstream::uniqueLetter();
00392   }
00393   template <class T,class O>
00394   std::string
00395   ValuesHolder<T,O>::name() const
00396   {
00397     std::ostringstream  os;
00398     os<<letter_<<"i";
00399     return os.str();
00400   }
00401   template <class T,class O>
00402   std::string
00403   ValuesHolder<T,O>::description() const
00404   {
00405     return description_;
00406   }
00407   //************************************************************
00408   // Implementation of argstream
00409   //************************************************************
00410   inline
00411   argstream::argstream(int argc,char** argv)
00412     : progName_(argv[0]),
00413       minusActive_(true),
00414       isOk_(true)
00415   {
00416     parse(argc,argv);
00417   }
00418   inline
00419   argstream::argstream(const char* c)
00420     : progName_(""),
00421       minusActive_(true),
00422       isOk_(true)
00423   {
00424     std::string s(c);
00425     // Build argc, argv from s. We must add a dummy first element for
00426     // progName because parse() expects it!!
00427     std::deque<std::string> args;
00428     args.push_back("");
00429     std::istringstream is(s);
00430     while (is.good())
00431     {
00432       std::string t;
00433       is>>t;
00434       args.push_back(t);
00435     }
00436     char* pargs[args.size()];
00437     char** p = pargs;
00438     for (std::deque<std::string>::const_iterator
00439                                          iter = args.begin();
00440                                  iter != args.end();++iter)
00441     {
00442       *p++ = const_cast<char*>(iter->c_str());
00443     }
00444     parse(args.size(),pargs);
00445   }
00446   inline void
00447   argstream::parse(int argc,char** argv)
00448   {
00449     // Run thru all arguments.
00450     // * it has -- in front : it is a long name option, if remainder is empty,
00451     //                        it is an error
00452     // * it has - in front  : it is a sequence of short name options, if
00453     //                        remainder is empty, deactivates option (- will
00454     //                        now be considered a char).
00455     // * if any other char, or if option was deactivated
00456     //                      : it is a value. Values are split in parameters
00457     //                      (immediately follow an option) and pure values.
00458     // Each time a value is parsed, if the previously parsed argument was an
00459     // option, then the option is linked to the value in case of it is a
00460     // option with parameter.  The subtle point is that when several options
00461     // are given with short names (ex: -abc equivalent to -a -b -c), the last
00462     // parsed option is -c).
00463     // Since we use map for option, any successive call overides the previous
00464     // one: foo -a -b -a hello is equivalent to foo -b -a hello
00465     // For values it is not true since we might have several times the same
00466     // value. 
00467     value_iterator* lastOption = NULL;
00468     for (char** a = argv,**astop=a+argc;++a!=astop;)
00469     {
00470       std::string s(*a);
00471       if (minusActive_ && s[0] == '-')
00472       {
00473                                 if (s.size() > 1 && s[1] == '-')
00474                                 {
00475                                         if (s.size() == 2)
00476                                         {
00477                                                 minusActive_ = false;
00478                                                 continue;
00479                                         }
00480                                         lastOption = &(options_[s.substr(2)] = values_.end());
00481                                 }
00482                                 else 
00483                                 {
00484                                         if (s.size() > 1)
00485                                         {
00486                                                 // Parse all chars, if it is a minus we have an error
00487                                                 for (std::string::const_iterator cter = s.begin();
00488                                                                  ++cter != s.end();)
00489                                                 {
00490                                                         if (*cter == '-')
00491                                                         {
00492                                                                 isOk_ = false;
00493                                                                 std::ostringstream os;
00494                                                                 os<<"- in the middle of a switch "<<a;
00495                                                                 errors_.push_back(os.str());
00496                                                                 break;
00497                                                         }
00498                                                         lastOption = &(options_[std::string(1,*cter)] = values_.end());
00499                                                 }
00500                                         }
00501                                         else
00502                                         {
00503                                                 isOk_ = false;
00504                                                 errors_.push_back("Invalid argument -");
00505                                                 break;
00506                                         }
00507                                 }
00508       }
00509       else
00510       {
00511                                 values_.push_back(s);
00512                                 if (lastOption != NULL)
00513                                 {
00514                                         *lastOption = --values_.end();
00515                                 }
00516                                 lastOption = NULL;
00517       }
00518     }
00519 #ifdef ARGSTREAM_DEBUG
00520     for (std::map<std::string,value_iterator>::const_iterator
00521                                          iter = options_.begin();iter != options_.end();++iter)
00522     {
00523       std::cout<<"DEBUG: option "<<iter->first;
00524       if (iter->second != values_.end())
00525       {
00526                                 std::cout<<" -> "<<*(iter->second);
00527       }
00528       std::cout<<std::endl;
00529     }
00530     for (std::list<std::string>::const_iterator
00531                                          iter = values_.begin();iter != values_.end();++iter)
00532     {
00533       std::cout<<"DEBUG: value  "<<*iter<<std::endl;
00534     }
00535 #endif // ARGSTREAM_DEBUG
00536   }
00537   inline bool
00538   argstream::isOk() const
00539   {
00540     return isOk_;
00541   }
00542   inline bool
00543   argstream::helpRequested() const
00544   {
00545     return helpRequested_;
00546   }
00547   inline std::string
00548   argstream::usage() const
00549   {
00550     std::ostringstream os;
00551     os<<"usage: "<<progName_<<cmdLine_<<'\n';
00552     unsigned int lmax = 0;
00553     for (std::deque<help_entry>::const_iterator
00554                                          iter = argHelps_.begin();iter != argHelps_.end();++iter)
00555     {
00556       if (lmax<iter->first.size()) lmax = iter->first.size();
00557     }  
00558     for (std::deque<help_entry>::const_iterator
00559                                          iter = argHelps_.begin();iter != argHelps_.end();++iter)
00560     {
00561       os<<'\t'<<iter->first<<std::string(lmax-iter->first.size(),' ')
00562                                 <<" : "<<iter->second<<'\n';
00563     }
00564     return os.str();
00565   }
00566   inline std::string
00567   argstream::errorLog() const
00568   {
00569     std::string s;
00570     for(std::deque<std::string>::const_iterator iter = errors_.begin();
00571                                 iter != errors_.end();++iter)
00572     {
00573       s += *iter;
00574       s += '\n';
00575     }
00576     return s;
00577   }
00578   inline char
00579   argstream::uniqueLetter()
00580   {
00581     static unsigned int c = 'a';
00582     return c++;
00583   }
00584   template<class T>
00585   argstream&
00586   operator>>(argstream& s,const ValueHolder<T>& v)
00587   {
00588     // Search in the options if there is any such option defined either with a
00589     // short name or a long name. If both are found, only the last one is
00590     // used.
00591 #ifdef ARGSTREAM_DEBUG    
00592     std::cout<<"DEBUG: searching "<<v.shortName_<<" "<<v.longName_<<std::endl;
00593 #endif    
00594     s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
00595     if (v.mandatory_)
00596     {
00597       if (!v.shortName_.empty())
00598       {
00599                                 s.cmdLine_ += " -";
00600                                 s.cmdLine_ += v.shortName_;
00601       }
00602       else
00603       {
00604                                 s.cmdLine_ += " --";
00605                                 s.cmdLine_ += v.longName_;
00606       }
00607       s.cmdLine_ += " value";
00608     }
00609     else
00610     {
00611       if (!v.shortName_.empty())
00612       {
00613                                 s.cmdLine_ += " [-";
00614                                 s.cmdLine_ += v.shortName_;
00615       }
00616       else
00617       {
00618                                 s.cmdLine_ += " [--";
00619                                 s.cmdLine_ += v.longName_;
00620       }  
00621       s.cmdLine_ += " value]";
00622 
00623     }
00624     std::map<std::string,argstream::value_iterator>::iterator iter =
00625       s.options_.find(v.shortName_);
00626     if (iter == s.options_.end())
00627     {
00628       iter = s.options_.find(v.longName_);
00629     }
00630     if (iter != s.options_.end())
00631     {
00632       // If we find counterpart for value holder on command line, either it
00633       // has an associated value in which case we assign it, or it has not, in
00634       // which case we have an error.
00635       if (iter->second != s.values_.end())
00636       {
00637 #ifdef ARGSTREAM_DEBUG
00638                                 std::cout<<"DEBUG: found value "<<*(iter->second)<<std::endl;
00639 #endif  
00640                                 ValueParser<T> p;
00641                                 *(v.value_) = p(*(iter->second));
00642                                 // The option and its associated value are removed, the subtle thing
00643                                 // is that someother options might have this associated value too,
00644                                 // which we must invalidate.
00645                                 s.values_.erase(iter->second);      
00646                                 for (std::map<std::string,argstream::value_iterator>::iterator
00647                                                          jter = s.options_.begin();jter != s.options_.end();++jter)
00648                                 {
00649                                         if (jter->second == iter->second)
00650                                         {
00651                                                 jter->second = s.values_.end();
00652                                         }
00653                                 }
00654                                 s.options_.erase(iter);
00655       }
00656       else
00657       {
00658                                 s.isOk_ = false;
00659                                 std::ostringstream  os;
00660                                 os<<"No value following switch "<<iter->first
00661                                         <<" on command line";
00662                                 s.errors_.push_back(os.str());
00663       }
00664     }
00665     else
00666     {
00667       if (v.mandatory_)
00668       {
00669                                 s.isOk_ = false;
00670                                 std::ostringstream  os;
00671                                 os<<"Mandatory parameter ";
00672                                 if (!v.shortName_.empty()) os<<'-'<<v.shortName_;
00673                                 if (!v.longName_.empty())
00674                                 {
00675                                         if (!v.shortName_.empty()) os<<'/';
00676                                         os<<"--"<<v.longName_;
00677                                 }
00678                                 os<<" missing";
00679                                 s.errors_.push_back(os.str());
00680       }
00681     }
00682     return s;
00683   }
00684   inline argstream&
00685   operator>>(argstream& s,const OptionHolder& v)
00686   {
00687     // Search in the options if there is any such option defined either with a
00688     // short name or a long name. If both are found, only the last one is
00689     // used.
00690 #ifdef ARGSTREAM_DEBUG    
00691     std::cout<<"DEBUG: searching "<<v.shortName_<<" "<<v.longName_<<std::endl;
00692 #endif
00693     s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
00694     {
00695       std::string c;
00696       if (!v.shortName_.empty())
00697       {
00698                                 c += " [-";
00699                                 c += v.shortName_;
00700       }
00701       else
00702       {
00703                                 c += " [--";
00704                                 c += v.longName_;
00705       }      
00706       c += "]";
00707       s.cmdLine_ = c+s.cmdLine_;
00708     }
00709     std::map<std::string,argstream::value_iterator>::iterator iter =
00710       s.options_.find(v.shortName_);
00711     if (iter == s.options_.end())
00712     {
00713       iter = s.options_.find(v.longName_);
00714     }
00715     if (iter != s.options_.end())
00716     {
00717       // If we find counterpart for value holder on command line then the
00718       // option is true and if an associated value was found, it is ignored
00719       if (v.value_ != NULL)
00720       {
00721                                 *(v.value_) = true;
00722       }
00723       else
00724       {
00725                                 s.helpRequested_ = true;
00726       }
00727       // The option only is removed
00728       s.options_.erase(iter);
00729     }
00730     else
00731     {
00732       if (v.value_ != NULL)
00733       {
00734                                 *(v.value_) = false;
00735       }
00736       else
00737       {
00738                                 s.helpRequested_ = false;
00739       }
00740     }
00741     return s;
00742   }
00743   template<class T,class O>
00744   argstream&
00745   operator>>(argstream& s,const ValuesHolder<T,O>& v)
00746   {
00747     s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
00748     {
00749       std::ostringstream os;
00750       os<<' '<<v.letter_<<'1';
00751       switch (v.len_)
00752       {
00753       case -1:
00754                                 os<<"...";
00755                                 break;
00756       case 1:
00757                                 break;
00758       default:
00759                                 os<<"..."<<v.letter_<<v.len_;
00760                                 break;
00761       }
00762       s.cmdLine_ += os.str();
00763     }
00764     std::list<std::string>::iterator first = s.values_.begin();
00765     // We add to the iterator as much values as we can, limited to the length
00766     // specified (if different of -1)
00767     int n = v.len_ != -1?v.len_:s.values_.size();
00768     while (first != s.values_.end() && n-->0)
00769     {
00770       // Read the value from the string *first
00771       ValueParser<T> p;
00772       *(v.value_++) = p(*first );
00773       s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
00774       // The value we just removed was maybe "remembered" by an option so we
00775       // remove it now.
00776       for (std::map<std::string,argstream::value_iterator>::iterator
00777                                                  jter = s.options_.begin();jter != s.options_.end();++jter)
00778       {
00779                                 if (jter->second == first)
00780                                 {
00781                                         jter->second = s.values_.end();
00782                                 }
00783       }
00784       ++first;
00785     }
00786     // Check if we have enough values
00787     if (n != 0)
00788     {
00789       s.isOk_ = false;
00790       std::ostringstream  os;
00791       os<<"Expecting "<<v.len_<<" values";
00792       s.errors_.push_back(os.str());
00793     }
00794     // Erase the values parsed
00795     s.values_.erase(s.values_.begin(),first);
00796     return s;
00797   }
00798   inline void
00799   argstream::defaultErrorHandling(bool ignoreUnused) const
00800   {
00801     if (helpRequested_)
00802     {
00803       std::cout<<usage();
00804       exit(1);
00805     }
00806     if (!isOk_)
00807     {
00808       std::cerr<<errorLog();
00809       exit(1);
00810     }
00811     if (!ignoreUnused &&
00812                                 (!values_.empty() || !options_.empty()))
00813     {
00814       std::cerr<<"Unused arguments"<<std::endl;
00815       exit(1);
00816     }
00817   }
00818 };
00819 #endif // ARGSTREAM_H
00820 
00821 // Local variables section.
00822 // This is only used by emacs!
00823 // Local Variables:
00824 // ff-search-directories: ("." "../../../src/xdkwrl/tools/")
00825 // End:

Generated on 28 Jun 2006 with doxygen version 1.4.4. Valid HTML 4.0! Valid CSS!