1 /* 2 * cFlexVar.h 3 * Avida 4 * 5 * Copyright 2007-2011 Michigan State University. All rights reserved. 6 * 7 * 8 * This file is part of Avida. 9 * 10 * Avida is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License 11 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 12 * 13 * Avida is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public License along with Avida. 17 * If not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 #ifndef cFlexVar_h 22 #define cFlexVar_h 23 24 #include "cString.h" 25 26 // This class is designed to allow generic core variables to be passed around, and for the receiver to be able 27 // to handle them however they like. Each instance of the class represents a single variable whose type can be 28 // requested and whose value can easily be converted as needed. 29 30 class cFlexVar { 31 public: 32 enum eFlexType { 33 TYPE_NONE = 0, 34 TYPE_INT = 1, 35 TYPE_CHAR = 2, 36 TYPE_DOUBLE = 3, 37 TYPE_STRING = 4, 38 TYPE_BOOL = 5 39 }; 40 41 private: 42 //////////////////////////////////////////////////////////// 43 // Base class for the internal type system.... 44 class cFlexVar_Base { 45 public: cFlexVar_Base()46 cFlexVar_Base() { ; } ~cFlexVar_Base()47 virtual ~cFlexVar_Base() { ; } 48 49 virtual bool AsBool() const = 0; 50 virtual int AsInt() const = 0; 51 virtual char AsChar() const = 0; 52 virtual double AsDouble() const = 0; 53 virtual void SetString(cString & in_str) const = 0; AsString()54 cString AsString() const { cString out_str; SetString(out_str); return out_str; } 55 GetType()56 virtual eFlexType GetType() const { return TYPE_NONE; } 57 virtual void Print(std::ostream& out) const = 0; 58 59 #define ABSTRACT_FLEX_VAR_BASE_OP(OP, RETURN_TYPE) \ 60 virtual RETURN_TYPE operator OP (bool in_var) const = 0; \ 61 virtual RETURN_TYPE operator OP (int in_var) const = 0; \ 62 virtual RETURN_TYPE operator OP (char in_var) const = 0; \ 63 virtual RETURN_TYPE operator OP (double in_var) const = 0; \ 64 virtual RETURN_TYPE operator OP (const cString & in_var) const = 0; 65 66 ABSTRACT_FLEX_VAR_BASE_OP(==, bool) 67 ABSTRACT_FLEX_VAR_BASE_OP(!=, bool) 68 ABSTRACT_FLEX_VAR_BASE_OP(<, bool) 69 ABSTRACT_FLEX_VAR_BASE_OP(>, bool) 70 ABSTRACT_FLEX_VAR_BASE_OP(<=, bool) 71 ABSTRACT_FLEX_VAR_BASE_OP(>=, bool) 72 }; 73 74 //////////////////////////////////////////////////////////// 75 // Internal class for managing int type...... 76 class cFlexVar_Bool : public cFlexVar_Base { 77 private: 78 bool m_value; 79 public: cFlexVar_Bool(bool in_val)80 cFlexVar_Bool(bool in_val) : m_value(in_val) { ; } ~cFlexVar_Bool()81 ~cFlexVar_Bool() { ; } 82 AsBool()83 bool AsBool() const { return m_value; } AsInt()84 int AsInt() const { return (int) m_value; } AsChar()85 char AsChar() const { return (char) m_value; } AsDouble()86 double AsDouble() const { return (double) m_value; } SetString(cString & in_str)87 void SetString(cString & in_str) const { if (m_value) in_str = "true"; else in_str = "false"; } 88 GetType()89 eFlexType GetType() const { return TYPE_BOOL; } Print(std::ostream & out)90 void Print(std::ostream& out) const { out << m_value; } 91 92 #define CREATE_FLEX_VAR_BOOL_MATH_OP(OP, RETURN_TYPE) \ 93 RETURN_TYPE operator OP (bool in_var) const { return (int)m_value OP in_var; } \ 94 RETURN_TYPE operator OP (int in_var) const { return (int)m_value OP in_var; } \ 95 RETURN_TYPE operator OP (char in_var) const { return (int)m_value OP (int) in_var; } \ 96 RETURN_TYPE operator OP (double in_var) const { return ((double) m_value) OP in_var; } \ 97 RETURN_TYPE operator OP (const cString & in_var) const { return ((double) m_value) OP in_var.AsDouble(); } 98 99 CREATE_FLEX_VAR_BOOL_MATH_OP(==, bool); 100 CREATE_FLEX_VAR_BOOL_MATH_OP(!=, bool); 101 CREATE_FLEX_VAR_BOOL_MATH_OP(<, bool); 102 CREATE_FLEX_VAR_BOOL_MATH_OP(>, bool); 103 CREATE_FLEX_VAR_BOOL_MATH_OP(<=, bool); 104 CREATE_FLEX_VAR_BOOL_MATH_OP(>=, bool); 105 }; 106 107 108 class cFlexVar_Int : public cFlexVar_Base { 109 private: 110 int m_value; 111 public: cFlexVar_Int(int in_val)112 cFlexVar_Int(int in_val) : m_value(in_val) { ; } ~cFlexVar_Int()113 ~cFlexVar_Int() { ; } 114 AsBool()115 bool AsBool() const { return (m_value); } AsInt()116 int AsInt() const { return m_value; } AsChar()117 char AsChar() const { return (char) m_value; } AsDouble()118 double AsDouble() const { return (double) m_value; } SetString(cString & in_str)119 void SetString(cString & in_str) const { in_str.Set("%d", m_value); } 120 GetType()121 eFlexType GetType() const { return TYPE_INT; } Print(std::ostream & out)122 void Print(std::ostream& out) const { out << m_value; } 123 124 #define CREATE_FLEX_VAR_INT_MATH_OP(OP, RETURN_TYPE) \ 125 RETURN_TYPE operator OP (bool in_var) const { return m_value OP (int)in_var; } \ 126 RETURN_TYPE operator OP (int in_var) const { return m_value OP in_var; } \ 127 RETURN_TYPE operator OP (char in_var) const { return m_value OP (int) in_var; } \ 128 RETURN_TYPE operator OP (double in_var) const { return ((double) m_value) OP in_var; } \ 129 RETURN_TYPE operator OP (const cString & in_var) const { return ((double) m_value) OP in_var.AsDouble(); } 130 131 CREATE_FLEX_VAR_INT_MATH_OP(==, bool); 132 CREATE_FLEX_VAR_INT_MATH_OP(!=, bool); 133 CREATE_FLEX_VAR_INT_MATH_OP(<, bool); 134 CREATE_FLEX_VAR_INT_MATH_OP(>, bool); 135 CREATE_FLEX_VAR_INT_MATH_OP(<=, bool); 136 CREATE_FLEX_VAR_INT_MATH_OP(>=, bool); 137 }; 138 139 140 //////////////////////////////////////////////////////////// 141 // Internal class for managing char type...... 142 143 class cFlexVar_Char : public cFlexVar_Base { 144 private: 145 char m_value; 146 public: cFlexVar_Char(char in_val)147 cFlexVar_Char(char in_val) : m_value(in_val) { ; } ~cFlexVar_Char()148 ~cFlexVar_Char() { ; } 149 AsBool()150 bool AsBool() const { return ((int)m_value); } AsInt()151 int AsInt() const { return (int) m_value; } AsChar()152 char AsChar() const { return m_value; } AsDouble()153 double AsDouble() const { return (double) m_value; } SetString(cString & in_str)154 void SetString(cString & in_str) const { in_str.Set("%c", m_value); } 155 GetType()156 eFlexType GetType() const { return TYPE_CHAR; } Print(std::ostream & out)157 void Print(std::ostream& out) const { out << m_value; } 158 159 #define CREATE_FLEX_VAR_CHAR_MATH_OP(OP, RETURN_TYPE) \ 160 RETURN_TYPE operator OP (bool in_var) const { return (int)m_value OP (int)in_var; } \ 161 RETURN_TYPE operator OP (int in_var) const { return ((int) m_value) OP in_var; } \ 162 RETURN_TYPE operator OP (char in_var) const { return m_value OP in_var; } \ 163 RETURN_TYPE operator OP (double in_var) const { return ((double) m_value) OP in_var; } \ 164 RETURN_TYPE operator OP (const cString & in_var) const { return cString(&m_value, 1) OP in_var; } 165 166 CREATE_FLEX_VAR_CHAR_MATH_OP(==, bool); 167 CREATE_FLEX_VAR_CHAR_MATH_OP(!=, bool); 168 CREATE_FLEX_VAR_CHAR_MATH_OP(<, bool); 169 CREATE_FLEX_VAR_CHAR_MATH_OP(>, bool); 170 CREATE_FLEX_VAR_CHAR_MATH_OP(<=, bool); 171 CREATE_FLEX_VAR_CHAR_MATH_OP(>=, bool); 172 }; 173 174 175 //////////////////////////////////////////////////////////// 176 // Internal class for managing double type...... 177 178 class cFlexVar_Double : public cFlexVar_Base { 179 private: 180 double m_value; 181 public: cFlexVar_Double(double in_val)182 cFlexVar_Double(double in_val) : m_value(in_val) { ; } ~cFlexVar_Double()183 ~cFlexVar_Double() { ; } 184 AsBool()185 bool AsBool() const { return ((int)m_value); } AsInt()186 int AsInt() const { return (int) m_value; } AsChar()187 char AsChar() const { return (char) m_value; } AsDouble()188 double AsDouble() const { return m_value; } SetString(cString & in_str)189 void SetString(cString & in_str) const { in_str.Set("%f", m_value); } 190 GetType()191 eFlexType GetType() const { return TYPE_DOUBLE; } Print(std::ostream & out)192 void Print(std::ostream& out) const { out << m_value; } 193 194 #define CREATE_FLEX_VAR_DOUBLE_MATH_OP(OP, RETURN_TYPE) \ 195 RETURN_TYPE operator OP (bool in_var) const { return m_value OP (double)in_var; } \ 196 RETURN_TYPE operator OP (int in_var) const { return m_value OP (double) in_var; } \ 197 RETURN_TYPE operator OP (char in_var) const { return m_value OP (double) in_var; } \ 198 RETURN_TYPE operator OP (double in_var) const { return m_value OP in_var; } \ 199 RETURN_TYPE operator OP (const cString & in_var) const { return m_value OP in_var.AsDouble(); } 200 201 CREATE_FLEX_VAR_DOUBLE_MATH_OP(==, bool); 202 CREATE_FLEX_VAR_DOUBLE_MATH_OP(!=, bool); 203 CREATE_FLEX_VAR_DOUBLE_MATH_OP(<, bool); 204 CREATE_FLEX_VAR_DOUBLE_MATH_OP(>, bool); 205 CREATE_FLEX_VAR_DOUBLE_MATH_OP(<=, bool); 206 CREATE_FLEX_VAR_DOUBLE_MATH_OP(>=, bool); 207 }; 208 209 210 //////////////////////////////////////////////////////////// 211 // Internal class for managing cString type...... 212 213 class cFlexVar_String : public cFlexVar_Base { 214 private: 215 cString m_value; 216 public: cFlexVar_String(const cString & in_val)217 cFlexVar_String(const cString & in_val) : m_value(in_val) { ; } ~cFlexVar_String()218 ~cFlexVar_String() { ; } 219 AsBool()220 bool AsBool() const 221 { 222 cString val(m_value); 223 val.ToUpper(); 224 225 if (val == "TRUE" || val == "T") return true; 226 if (val == "FALSE" || val == "F") return false; 227 228 return (val.AsInt()); 229 } 230 AsInt()231 int AsInt() const { return m_value.AsInt(); } AsChar()232 char AsChar() const { return m_value[0]; } AsDouble()233 double AsDouble() const { return m_value.AsDouble(); } SetString(cString & in_str)234 void SetString(cString & in_str) const { in_str = m_value; } 235 GetType()236 eFlexType GetType() const { return TYPE_STRING; } Print(std::ostream & out)237 void Print(std::ostream& out) const { out << m_value; } 238 239 #define CREATE_FLEX_VAR_STRING_MATH_OP(OP, RETURN_TYPE) \ 240 RETURN_TYPE operator OP (bool in_var) const { return AsBool() OP in_var; } \ 241 RETURN_TYPE operator OP (int in_var) const { return m_value.AsDouble() OP (double) in_var; } \ 242 RETURN_TYPE operator OP (char in_var) const { return m_value OP cString(&in_var, 1); } \ 243 RETURN_TYPE operator OP (double in_var) const { return m_value.AsDouble() OP in_var; } \ 244 RETURN_TYPE operator OP (const cString & in_var) const { return m_value OP in_var; } 245 246 CREATE_FLEX_VAR_STRING_MATH_OP(==, bool); 247 CREATE_FLEX_VAR_STRING_MATH_OP(!=, bool); 248 CREATE_FLEX_VAR_STRING_MATH_OP(<, bool); 249 CREATE_FLEX_VAR_STRING_MATH_OP(>, bool); 250 CREATE_FLEX_VAR_STRING_MATH_OP(<=, bool); 251 CREATE_FLEX_VAR_STRING_MATH_OP(>=, bool); 252 }; 253 254 cFlexVar_Base* m_var; 255 256 public: 257 // Setup constructors to be able to build this variable from whatever input we need. cFlexVar(const cFlexVar & in_var)258 cFlexVar(const cFlexVar & in_var) : m_var(NULL) { 259 if (in_var.GetType() == TYPE_INT) m_var = new cFlexVar_Int( in_var.AsInt() ); 260 else if (in_var.GetType() == TYPE_CHAR) m_var = new cFlexVar_Char( in_var.AsChar() ); 261 else if (in_var.GetType() == TYPE_DOUBLE) m_var = new cFlexVar_Double( in_var.AsDouble() ); 262 else if (in_var.GetType() == TYPE_STRING) m_var = new cFlexVar_String( in_var.AsString() ); 263 } m_var(new cFlexVar_Int (in_value))264 cFlexVar(int in_value = 0) : m_var(new cFlexVar_Int(in_value)) { ; } cFlexVar(char in_value)265 cFlexVar(char in_value) : m_var(new cFlexVar_Char(in_value)) { ; } cFlexVar(double in_value)266 cFlexVar(double in_value) : m_var(new cFlexVar_Double(in_value)) { ; } cFlexVar(const cString & in_value)267 cFlexVar(const cString & in_value) : m_var(new cFlexVar_String(in_value)) { ; } ~cFlexVar()268 ~cFlexVar() { delete m_var; } 269 270 // Setup an accessor to determine the native type of this variable. GetType()271 eFlexType GetType() const { return m_var->GetType(); } Print(std::ostream & out)272 void Print(std::ostream& out) const { m_var->Print(out); } 273 274 275 // Setup accessors to get this variable as any type we might need. AsBool()276 bool AsBool() const { return m_var->AsBool(); } AsInt()277 int AsInt() const { return m_var->AsInt(); } AsChar()278 char AsChar() const { return m_var->AsChar(); } AsDouble()279 double AsDouble() const { return m_var->AsDouble(); } AsString()280 cString AsString() const { return m_var->AsString(); } SetString(cString & in_str)281 void SetString(cString & in_str) const { m_var->SetString(in_str); } 282 283 template<class Type> Type As() const; 284 285 // Setup a way to convert the native types MakeInt()286 int MakeInt() { int val = AsInt(); delete m_var; m_var = new cFlexVar_Int(val); return val; } MakeChar()287 char MakeChar() { char val = AsChar(); delete m_var; m_var = new cFlexVar_Char(val); return val; } MakeDouble()288 double MakeDouble() { double val = AsDouble(); delete m_var; m_var = new cFlexVar_Double(val); return val; } MakeString()289 cString MakeString() { cString val = AsString(); delete m_var; m_var = new cFlexVar_String(val); return val; } 290 291 // Setup assignment operators... 292 cFlexVar & operator=(const cFlexVar & in_var) { 293 delete m_var; 294 if (in_var.GetType() == TYPE_INT) m_var = new cFlexVar_Int( in_var.AsInt() ); 295 else if (in_var.GetType() == TYPE_CHAR) m_var = new cFlexVar_Char( in_var.AsChar() ); 296 else if (in_var.GetType() == TYPE_DOUBLE) m_var = new cFlexVar_Double( in_var.AsDouble() ); 297 else if (in_var.GetType() == TYPE_STRING) m_var = new cFlexVar_String( in_var.AsString() ); 298 return *this; 299 } 300 cFlexVar& operator=(int in_value) { delete m_var; m_var = new cFlexVar_Int(in_value); return *this; } 301 cFlexVar& operator=(char in_value) { delete m_var; m_var = new cFlexVar_Char(in_value); return *this; } 302 cFlexVar& operator=(double in_value) { delete m_var; m_var = new cFlexVar_Double(in_value); return *this; } 303 cFlexVar& operator=(const cString & in_value) { delete m_var; m_var = new cFlexVar_String(in_value); return *this; } 304 cFlexVar& operator=(const char * in_value) { delete m_var; m_var = new cFlexVar_String(in_value); return *this; } 305 306 // The following macro will forward all of the commands with the associated operator to the internal class. 307 #define FORWARD_FLEX_VAR_OP(OP, RETURN_TYPE) \ 308 RETURN_TYPE operator OP(bool in_var) const { return (*m_var) OP in_var; } \ 309 RETURN_TYPE operator OP(int in_var) const { return (*m_var) OP in_var; } \ 310 RETURN_TYPE operator OP(char in_var) const { return (*m_var) OP in_var; } \ 311 RETURN_TYPE operator OP(double in_var) const { return (*m_var) OP in_var; } \ 312 RETURN_TYPE operator OP(const cString & in_var) const { return (*m_var) OP in_var; } \ 313 RETURN_TYPE operator OP(const cFlexVar & in_var) const { \ 314 const eFlexType type = in_var.GetType(); \ 315 if (type == TYPE_INT) return (*m_var) OP in_var.AsInt(); \ 316 else if (type == TYPE_CHAR) return (*m_var) OP in_var.AsChar(); \ 317 else if (type == TYPE_DOUBLE) return (*m_var) OP in_var.AsDouble(); \ 318 else /* if (type == TYPE_STRING) */ return (*m_var) OP in_var.AsString(); \ 319 } 320 321 FORWARD_FLEX_VAR_OP(==, bool) 322 FORWARD_FLEX_VAR_OP(!=, bool) 323 FORWARD_FLEX_VAR_OP(<, bool) 324 FORWARD_FLEX_VAR_OP(>, bool) 325 FORWARD_FLEX_VAR_OP(<=, bool) 326 FORWARD_FLEX_VAR_OP(>=, bool) 327 328 }; 329 330 template<> inline bool cFlexVar::As<bool>() const { return m_var->AsBool(); } 331 template<> inline int cFlexVar::As<int>() const { return m_var->AsInt(); } 332 template<> inline char cFlexVar::As<char>() const { return m_var->AsChar(); } 333 template<> inline double cFlexVar::As<double>() const { return m_var->AsDouble(); } 334 template<> inline cString cFlexVar::As<cString>() const { return m_var->AsString(); } 335 336 337 inline std::ostream& operator << (std::ostream& out, const cFlexVar & entry) 338 { 339 entry.Print(out); 340 return out; 341 } 342 343 344 #endif 345