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