00001 /* 00002 * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 * 00020 */ 00021 00022 #ifndef _ENUM_H_ 00023 #define _ENUM_H_ 00024 #include <exception> 00025 #include <iosfwd> 00026 #include <string> 00027 #include "Assert.hxx" 00028 #include "Component.hxx" 00029 00030 namespace CLAM { 00031 00032 // TODO: Integrate this excepcion class with CLAM exception standards 00033 class IllegalValue : public std::exception { 00034 public: 00035 IllegalValue(const IllegalValue & e): msg(e.msg) {}; 00036 IllegalValue(const std::string & s) : msg(s) {}; 00037 virtual ~IllegalValue() throw() {}; 00038 std::string msg; 00039 }; 00040 00041 00093 class Enum : public Component { 00094 00095 // Internal Types 00096 public: 00097 typedef int tValue; 00098 typedef struct {tValue value; const char*name;} tEnumValue; 00099 00100 // Attributes 00101 private: 00102 const tEnumValue * mEnumValues; 00103 tValue mValue; 00104 00107 00108 protected: 00116 Enum (const tEnumValue * values, const tValue & value) /* throw IllegalValue */ { 00117 mEnumValues = values; 00118 SetValue(value); 00119 } 00127 Enum (const tEnumValue * values, const std::string & value) /* throw IllegalValue */ { 00128 mEnumValues = values; 00129 SetValue(value); 00130 }; 00131 public: 00133 virtual ~Enum (); 00134 const char * GetClassName() const {return NULL;} 00136 00137 // Operations 00138 public: 00142 const tEnumValue * GetSymbolMap() const { 00143 return mEnumValues; 00144 } 00145 00150 void SetValue(const tValue v) { 00151 CLAM_BEGIN_DEBUG_CHECK 00152 for (int i = 0; mEnumValues[i].name; i++) { 00153 if (v==mEnumValues[i].value) { 00154 mValue = v; 00155 return; 00156 } 00157 } 00158 CLAM_ASSERT(false, "Invalid value for an Enum"); 00159 CLAM_END_DEBUG_CHECK 00160 mValue = v; 00161 } 00171 void SetValueSafely(const tValue v) throw (IllegalValue) { 00172 for (int i = 0; mEnumValues[i].name; i++) { 00173 if (v==mEnumValues[i].value) { 00174 mValue = v; 00175 return; 00176 } 00177 } 00178 throw IllegalValue("Invalid value for an Enum"); 00179 } 00184 void SetValue(const std::string & s) 00185 { 00186 for (int i = 0; mEnumValues[i].name; i++) { 00187 if (s.compare(mEnumValues[i].name)==0) { 00188 mValue = mEnumValues[i].value; 00189 return; 00190 } 00191 } 00192 CLAM_ASSERT(false, "Illegal literal for an Enum"); 00193 } 00194 /* 00195 * Changes the value safely. 00196 * That is it checks the value is ok for the enum and throws a 00197 * catchable exception if not. 00198 * @param s The new symbolic value 00199 * @throw IllegalValue when the value is not valid for the enum 00200 * @todo Fill IllegalValue with useful information to recover 00201 * instead a insightfull string. 00202 */ 00203 void SetValueSafely(const std::string & s) throw (IllegalValue) 00204 { 00205 for (int i = 0; mEnumValues[i].name; i++) { 00206 if (s.compare(mEnumValues[i].name)==0) { 00207 mValue = mEnumValues[i].value; 00208 return; 00209 } 00210 } 00211 throw IllegalValue("Illegal literal for an Enum."); 00212 } 00213 00218 tValue GetValue() const { 00219 return mValue; 00220 } 00221 00226 std::string GetString() const throw (IllegalValue) 00227 { 00228 for (int i = 0; mEnumValues[i].name; i++) { 00229 if (mValue==mEnumValues[i].value) 00230 return mEnumValues[i].name; 00231 } 00232 CLAM_ASSERT(false, "Illegal numeric value for an Enum"); 00233 return "IllegalValue"; 00234 } 00235 00236 Enum & operator = (const tValue & v) throw (IllegalValue) { 00237 SetValue(v); 00238 return *this; 00239 } 00240 00241 Enum & operator = (const std::string & v) throw (IllegalValue) { 00242 SetValue(v); 00243 return *this; 00244 } 00245 00246 Enum & operator = (const Enum & v) throw (IllegalValue) { 00247 SetValue(tValue(v)); 00248 return *this; 00249 } 00250 00255 operator tValue() const { 00256 return mValue; 00257 } 00258 00259 // Component Protocol 00260 public: 00267 virtual Component * Species () const = 0; 00268 00272 virtual Component * DeepCopy () const { 00273 Enum * pe = (Enum*)Species(); 00274 pe->SetValue(mValue); 00275 return pe; 00276 } 00277 00281 virtual Component * ShallowCopy () const { 00282 Enum * pe = (Enum*)Species(); 00283 pe->SetValue(mValue); 00284 return pe; 00285 } 00286 00294 virtual void StoreOn (Storage & storage) const; 00295 00303 virtual void LoadFrom (Storage & storage); 00304 00305 00306 }; 00307 00314 std::ostream & operator << (std::ostream & os, const Enum & e) throw (IllegalValue); 00315 00322 std::istream & operator >> (std::istream & os, Enum & e) throw (IllegalValue); 00323 00324 } 00325 #endif // _ENUM_H_ 00326