Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/CommandLineOptions.h
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2005 George Tzanetakis <gtzan@cs.uvic.ca>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 
00020 #ifndef MARSYAS_COMMANDLINEOPTIONS_H
00021 #define MARSYAS_COMMANDLINEOPTIONS_H
00022 
00023 #include <marsyas/common_header.h>
00024 
00025 #include <vector>
00026 #include <string>
00027 #include <map>
00028 #include <iostream>
00029 #include <typeinfo>
00030 
00031 namespace Marsyas
00032 {
00033 
00039 class marsyas_EXPORT CommandLineOptions
00040 {
00041 private:
00042 
00043   struct Option
00044   {
00045     Option(): is_set(false) {}
00046     virtual ~Option() {}
00047     virtual bool parse_value( std::istringstream & argument ) = 0;
00048     bool is_set;
00049     std::string short_name;
00050     std::string value_name;
00051     std::string description;
00052   };
00053 
00054   template <typename T>
00055   struct OptionT : public Option
00056   {
00057     OptionT( const T & default_value ):
00058       default_value(default_value),
00059       value()
00060     {}
00061     bool parse_value( std::istringstream & argument )
00062     {
00063       argument >> value;
00064       bool ok = !argument.fail();
00065       if (ok)
00066         is_set = true;
00067       return ok;
00068     }
00069     T default_value;
00070     T value;
00071   };
00072 
00073   template <typename T> OptionT<T> * option_cast(Option *option) const
00074   {
00075     if (typeid(*option) == typeid(OptionT<T>))
00076       return static_cast<OptionT<T>*>(option);
00077     else
00078       return 0;
00079   }
00080 
00081   std::vector<std::string> m_arguments;
00082   std::vector<std::string> m_remaining;
00083 
00084   std::map<std::string, std::string> m_long_names;
00085   std::map<std::string, Option *> m_options;
00086 
00087   template <typename T>
00088   void define_private(const std::string & long_name,
00089                       const std::string & short_name,
00090                       const std::string & value_name,
00091                       const std::string & description,
00092                       const T & default_value = T())
00093   {
00094     Option *option = new OptionT<T>(default_value);
00095     option->short_name = short_name;
00096     option->value_name = value_name;
00097     option->description = description;
00098     m_options[long_name] = option;
00099     if (!short_name.empty())
00100       m_long_names[short_name] = long_name;
00101   }
00102 
00103 public:
00104   CommandLineOptions();
00105   virtual ~CommandLineOptions();
00106 
00107   void print() const;
00108 
00109   bool readOptions(int argc, const char** argv);
00110 
00111   template <typename T>
00112   void define(const std::string & long_name,
00113               char short_name,
00114               const std::string & value_name,
00115               const std::string & description,
00116               const T & default_value = T())
00117   {
00118     define_private(long_name,
00119                    std::string(1, short_name),
00120                    value_name,
00121                    description,
00122                    default_value);
00123   }
00124 
00125   template <typename T>
00126   void define(const std::string & long_name,
00127               const std::string & value_name,
00128               const std::string & description,
00129               const T & default_value = T())
00130   {
00131     define_private(long_name,
00132                    std::string(),
00133                    value_name,
00134                    description,
00135                    default_value);
00136   }
00137 
00138   template <typename T>
00139   void define_old_style(const std::string & long_name,
00140                         const std::string & short_name,
00141                         const std::string & value_name,
00142                         const std::string & description,
00143                         const T & default_value = T())
00144   {
00145     define_private(long_name, short_name, value_name, description, default_value);
00146   }
00147 
00148   bool has( const std::string & long_name ) const
00149   {
00150     std::map<std::string, Option*>::const_iterator it = m_options.find(long_name);
00151     return (it != m_options.end() && (it->second->is_set));
00152   }
00153 
00154   template<typename T>
00155   T value( const std::string & long_name ) const
00156   {
00157     std::map<std::string, Option*>::const_iterator it = m_options.find(long_name);
00158     if (it == m_options.end())
00159       return T();
00160     OptionT<T> *typed_option = option_cast<T>(it->second);
00161     if (!typed_option)
00162       return T();
00163     return typed_option->is_set ? typed_option->value : typed_option->default_value;
00164   }
00165 
00166   void addBoolOption(const std::string & long_name,
00167                      const std::string & short_name,
00168                      bool value = false)
00169   {
00170     define_private(long_name, short_name, "", "", value);
00171   }
00172 
00173   void addRealOption(const std::string & long_name,
00174                      const std::string & short_name,
00175                      mrs_real value)
00176   {
00177     define_private(long_name, short_name, "", "", value);
00178   }
00179 
00180   void addNaturalOption(const std::string & long_name,
00181                         const std::string & short_name,
00182                         mrs_natural value)
00183   {
00184     define_private(long_name, short_name, "", "", value);
00185   }
00186 
00187   void addStringOption(const std::string & long_name,
00188                        const std::string & short_name,
00189                        const std::string & value)
00190   {
00191     define_private(long_name, short_name, "", "", value);
00192   }
00193 
00194   bool getBoolOption(const std::string & long_name) const
00195   {
00196     return has(long_name);
00197   }
00198 
00199   mrs_natural getNaturalOption(const std::string & long_name) const
00200   {
00201     return value<mrs_natural>(long_name);
00202   }
00203 
00204   mrs_real getRealOption(const std::string & long_name) const
00205   {
00206     return value<mrs_real>(long_name);
00207   }
00208 
00209   std::string getStringOption(const std::string & long_name) const
00210   {
00211     return value<std::string>(long_name);
00212   }
00213 
00214   const std::vector<std::string> & getRemaining() const
00215   {
00216     return m_remaining;
00217   }
00218 };
00219 
00220 template <>
00221 struct CommandLineOptions::OptionT<bool> : public CommandLineOptions::Option
00222 {
00223   OptionT(bool set) { is_set = set; }
00224   bool parse_value( std::istringstream& ) { return false; }
00225 };
00226 
00227 template <> inline
00228 bool CommandLineOptions::value<bool>( const std::string & long_name ) const
00229 {
00230   return has(long_name);
00231 }
00232 
00233 } //namespace Marsyas
00234 
00235 #endif