Marsyas
0.6.0-alpha
|
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