Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core3/src/util/MultiType.h @ 1716

Last change on this file since 1716 was 1716, checked in by landauf, 16 years ago

Added new 'MultiType', replacing MultiTypePrimitive, MultiTypeString and MultiTypeMath. MultiType can hold all types MultiTypeMath was able to hold, namely all primitives, pointers, string and several math objects (vector2, 3 and 4, quaternion, colourvalue, radian, degree).

The new MultiType has a completely changed behaviour, I'll explain this on a wiki page somewhen.
But to say the most important things in a few words:
The MultiType has a fixed type. This type is determined by the first assigned value (by using setValue(value), operator=(value) or MultiType(value)). Every other value getting assigned later, will be converted to the first type. But you can change the type (setType<T>()), convert the value (convert<T>()) or force the type of a newly assigned value manually (setValue<T>(value)) by using template functions.

In contrast, the old MultiTypeMath changed it's internal type whenever a new type was assigned. So be aware of this important change.

At the moment I can't see any issues, but there might very well be several problems yet to discover, so further tests will be done.

  • Property svn:eol-style set to native
File size: 24.0 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#ifndef _MultiType_H__
30#define _MultiType_H__
31
32#include "UtilPrereqs.h"
33
34#include <boost/static_assert.hpp>
35
36#include "Math.h"
37
38// disable annoying warning about multiple assignment operators
39#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
40#pragma warning(push)
41#pragma warning(disable:4522)
42#endif
43
44enum _UtilExport MT_Type
45{
46    MT_null,
47    MT_char,
48    MT_uchar,
49    MT_short,
50    MT_ushort,
51    MT_int,
52    MT_uint,
53    MT_long,
54    MT_ulong,
55    MT_longlong,
56    MT_ulonglong,
57    MT_float,
58    MT_double,
59    MT_longdouble,
60    MT_bool,
61    MT_void,
62    MT_string,
63    MT_vector2,
64    MT_vector3,
65    MT_vector4,
66    MT_colourvalue,
67    MT_quaternion,
68    MT_radian,
69    MT_degree
70};
71
72class _UtilExport MultiType
73{
74    friend std::ostream& operator<<(std::ostream& outstream, const MultiType& mt);
75
76    struct _UtilExport MT_ValueBase
77    {
78        virtual ~MT_ValueBase() {}
79
80        virtual MT_ValueBase* clone() const = 0;
81
82        virtual void setValue(const char& value)                 = 0;
83        virtual void setValue(const unsigned char& value)        = 0;
84        virtual void setValue(const short& value)                = 0;
85        virtual void setValue(const unsigned short& value)       = 0;
86        virtual void setValue(const int& value)                  = 0;
87        virtual void setValue(const unsigned int& value)         = 0;
88        virtual void setValue(const long& value)                 = 0;
89        virtual void setValue(const unsigned long& value)        = 0;
90        virtual void setValue(const long long& value)            = 0;
91        virtual void setValue(const unsigned long long& value)   = 0;
92        virtual void setValue(const float& value)                = 0;
93        virtual void setValue(const double& value)               = 0;
94        virtual void setValue(const long double& value)          = 0;
95        virtual void setValue(const bool& value)                 = 0;
96        virtual void setValue(      void* const& value)          = 0;
97        virtual void setValue(const std::string& value)          = 0;
98        virtual void setValue(const orxonox::Vector2& value)     = 0;
99        virtual void setValue(const orxonox::Vector3& value)     = 0;
100        virtual void setValue(const orxonox::Vector4& value)     = 0;
101        virtual void setValue(const orxonox::ColourValue& value) = 0;
102        virtual void setValue(const orxonox::Quaternion& value)  = 0;
103        virtual void setValue(const orxonox::Radian& value)      = 0;
104        virtual void setValue(const orxonox::Degree& value)      = 0;
105
106        virtual operator char()                 const = 0;
107        virtual operator unsigned char()        const = 0;
108        virtual operator short()                const = 0;
109        virtual operator unsigned short()       const = 0;
110        virtual operator int()                  const = 0;
111        virtual operator unsigned int()         const = 0;
112        virtual operator long()                 const = 0;
113        virtual operator unsigned long()        const = 0;
114        virtual operator long long()            const = 0;
115        virtual operator unsigned long long()   const = 0;
116        virtual operator float()                const = 0;
117        virtual operator double()               const = 0;
118        virtual operator long double()          const = 0;
119        virtual operator bool()                 const = 0;
120        virtual operator void*()                const = 0;
121        virtual operator std::string()          const = 0;
122        virtual operator orxonox::Vector2()     const = 0;
123        virtual operator orxonox::Vector3()     const = 0;
124        virtual operator orxonox::Vector4()     const = 0;
125        virtual operator orxonox::ColourValue() const = 0;
126        virtual operator orxonox::Quaternion()  const = 0;
127        virtual operator orxonox::Radian()      const = 0;
128        virtual operator orxonox::Degree()      const = 0;
129
130        virtual void toString(std::ostream& outstream) const = 0;
131    };
132
133    public:
134        inline                       MultiType()                       : value_(0), type_(MT_null) {}
135        template <typename V> inline MultiType(const V& value)         : value_(0), type_(MT_null) { this->assignValue(value); }
136        inline                       MultiType(const MultiType& other) : value_(0), type_(MT_null) { this->setValue(other); }
137        inline                       MultiType(MT_Type type)           : value_(0), type_(MT_null) { this->setType(type); }
138        ~MultiType() { if (this->value_) { delete this->value_; } }
139
140        template <typename V>             inline MultiType& operator=(const V& value)         { this->setValue(value);          return (*this); }
141        template <typename T, typename V> inline MultiType& operator=(const V& value)         { this->assignValue((T)value);    return (*this); }
142        inline                                   MultiType& operator=(const MultiType& other) { this->setValue(other);          return (*this); }
143        inline                                   MultiType& operator=(MT_Type type)           { this->setType(type);            return (*this); }
144
145        template <typename V> inline void             setValue(const V& value)         { if (this->value_) { this->value_->setValue(value); } else { this->createNewValueContainer(value); } }
146        template <typename V> inline void             setValue(V* value)               { if (this->value_) { this->value_->setValue((void*)value); } else { this->createNewValueContainer((void*)value); } }
147        inline void                                   setValue(const char* value);
148        inline void                                   setValue(const MultiType& other) { this->type_ = other.type_; this->value_ = (other.value_) ? other.value_->clone() : 0; }
149        template <typename T, typename V> inline void setValue(const V& value)         { this->assignValue((T)value); }
150
151        template <typename T> inline void convert() { this->setValue<T>(this->operator T()); }
152
153        inline void                       reset() { if (this->value_) { delete this->value_; this->value_ = 0; } this->type_ = MT_null; }
154
155        template <typename T> inline void setType()                       { this->assignValue(T()); }
156        inline void                       setType(const MultiType& other) { this->setType(other.type_); }
157        void                              setType(MT_Type type);
158
159        operator char()                  const;
160        operator unsigned char()         const;
161        operator short()                 const;
162        operator unsigned short()        const;
163        operator int()                   const;
164        operator unsigned int()          const;
165        operator long()                  const;
166        operator unsigned long()         const;
167        operator long long()             const;
168        operator unsigned long long()    const;
169        operator float()                 const;
170        operator double()                const;
171        operator long double()           const;
172        operator bool()                  const;
173        operator void*()                 const;
174        operator std::string()           const;
175        operator orxonox::Vector2()      const;
176        operator orxonox::Vector3()      const;
177        operator orxonox::Vector4()      const;
178        operator orxonox::ColourValue()  const;
179        operator orxonox::Quaternion()   const;
180        operator orxonox::Radian()       const;
181        operator orxonox::Degree()       const;
182        template <class T> operator T*() const { return ((T*)this->operator void*()); }
183
184        inline void getValue(char*                 value) const { if (this->value_) { (*value) = (*this->value_); } }
185        inline void getValue(unsigned char*        value) const { if (this->value_) { (*value) = (*this->value_); } }
186        inline void getValue(short*                value) const { if (this->value_) { (*value) = (*this->value_); } }
187        inline void getValue(unsigned short*       value) const { if (this->value_) { (*value) = (*this->value_); } }
188        inline void getValue(int*                  value) const { if (this->value_) { (*value) = (*this->value_); } }
189        inline void getValue(unsigned int*         value) const { if (this->value_) { (*value) = (*this->value_); } }
190        inline void getValue(long*                 value) const { if (this->value_) { (*value) = (*this->value_); } }
191        inline void getValue(unsigned long*        value) const { if (this->value_) { (*value) = (*this->value_); } }
192        inline void getValue(long long*            value) const { if (this->value_) { (*value) = (*this->value_); } }
193        inline void getValue(unsigned long long*   value) const { if (this->value_) { (*value) = (*this->value_); } }
194        inline void getValue(float*                value) const { if (this->value_) { (*value) = (*this->value_); } }
195        inline void getValue(double*               value) const { if (this->value_) { (*value) = (*this->value_); } }
196        inline void getValue(long double*          value) const { if (this->value_) { (*value) = (*this->value_); } }
197        inline void getValue(bool*                 value) const { if (this->value_) { (*value) = (*this->value_); } }
198        inline void getValue(void*                 value) const { if (this->value_) {   value  = (*this->value_); } }
199        inline void getValue(std::string*          value) const { if (this->value_) { (*value) = this->value_->operator std::string();          } }
200        inline void getValue(orxonox::Vector2*     value) const { if (this->value_) { (*value) = this->value_->operator orxonox::Vector2();     } }
201        inline void getValue(orxonox::Vector3*     value) const { if (this->value_) { (*value) = this->value_->operator orxonox::Vector3();     } }
202        inline void getValue(orxonox::Vector4*     value) const { if (this->value_) { (*value) = this->value_->operator orxonox::Vector4();     } }
203        inline void getValue(orxonox::ColourValue* value) const { if (this->value_) { (*value) = this->value_->operator orxonox::ColourValue(); } }
204        inline void getValue(orxonox::Quaternion*  value) const { if (this->value_) { (*value) = this->value_->operator orxonox::Quaternion();  } }
205        inline void getValue(orxonox::Radian*      value) const { if (this->value_) { (*value) = this->value_->operator orxonox::Radian();      } }
206        inline void getValue(orxonox::Degree*      value) const { if (this->value_) { (*value) = this->value_->operator orxonox::Degree();      } }
207
208        inline MT_Type                    getType()            const { return this->type_; }
209        inline bool                       isType(MT_Type type) const { return (this->type_ == type); }
210        template <typename T> inline bool isType()             const { return false; }
211        std::string                       getTypename()        const;
212
213        inline std::string toString() const { return this->operator std::string(); }
214
215    private:
216        inline void assignValue(const char& value)                 { if (this->value_ && this->type_ == MT_char)        { this->value_->setValue(value); } else { this->changeValueContainer<char>(value);                 this->type_ = MT_char;        } }
217        inline void assignValue(const unsigned char& value)        { if (this->value_ && this->type_ == MT_uchar)       { this->value_->setValue(value); } else { this->changeValueContainer<unsigned char>(value);        this->type_ = MT_uchar;       } }
218        inline void assignValue(const short& value)                { if (this->value_ && this->type_ == MT_short)       { this->value_->setValue(value); } else { this->changeValueContainer<short>(value);                this->type_ = MT_short;       } }
219        inline void assignValue(const unsigned short& value)       { if (this->value_ && this->type_ == MT_ushort)      { this->value_->setValue(value); } else { this->changeValueContainer<unsigned short>(value);       this->type_ = MT_ushort;      } }
220        inline void assignValue(const int& value)                  { if (this->value_ && this->type_ == MT_int)         { this->value_->setValue(value); } else { this->changeValueContainer<int>(value);                  this->type_ = MT_int;         } }
221        inline void assignValue(const unsigned int& value)         { if (this->value_ && this->type_ == MT_uint)        { this->value_->setValue(value); } else { this->changeValueContainer<unsigned int>(value);         this->type_ = MT_uint;        } }
222        inline void assignValue(const long& value)                 { if (this->value_ && this->type_ == MT_long)        { this->value_->setValue(value); } else { this->changeValueContainer<long>(value);                 this->type_ = MT_long;        } }
223        inline void assignValue(const unsigned long& value)        { if (this->value_ && this->type_ == MT_ulong)       { this->value_->setValue(value); } else { this->changeValueContainer<unsigned long>(value);        this->type_ = MT_ulong;       } }
224        inline void assignValue(const long long& value)            { if (this->value_ && this->type_ == MT_longlong)    { this->value_->setValue(value); } else { this->changeValueContainer<long long>(value);            this->type_ = MT_longlong;    } }
225        inline void assignValue(const unsigned long long& value)   { if (this->value_ && this->type_ == MT_ulonglong)   { this->value_->setValue(value); } else { this->changeValueContainer<unsigned long long>(value);   this->type_ = MT_ulonglong;   } }
226        inline void assignValue(const float& value)                { if (this->value_ && this->type_ == MT_float)       { this->value_->setValue(value); } else { this->changeValueContainer<float>(value);                this->type_ = MT_float;       } }
227        inline void assignValue(const double& value)               { if (this->value_ && this->type_ == MT_double)      { this->value_->setValue(value); } else { this->changeValueContainer<double>(value);               this->type_ = MT_double;      } }
228        inline void assignValue(const long double& value)          { if (this->value_ && this->type_ == MT_longdouble)  { this->value_->setValue(value); } else { this->changeValueContainer<long double>(value);          this->type_ = MT_longdouble;  } }
229        inline void assignValue(const bool& value)                 { if (this->value_ && this->type_ == MT_bool)        { this->value_->setValue(value); } else { this->changeValueContainer<bool>(value);                 this->type_ = MT_bool;        } }
230        inline void assignValue(      void* const& value)          { if (this->value_ && this->type_ == MT_void)        { this->value_->setValue(value); } else { this->changeValueContainer<void*>(value);                this->type_ = MT_void;        } }
231        inline void assignValue(const std::string& value)          { if (this->value_ && this->type_ == MT_string)      { this->value_->setValue(value); } else { this->changeValueContainer<std::string>(value);          this->type_ = MT_string;      } }
232        inline void assignValue(const orxonox::Vector2& value)     { if (this->value_ && this->type_ == MT_vector2)     { this->value_->setValue(value); } else { this->changeValueContainer<orxonox::Vector2>(value);     this->type_ = MT_vector2;     } }
233        inline void assignValue(const orxonox::Vector3& value)     { if (this->value_ && this->type_ == MT_vector3)     { this->value_->setValue(value); } else { this->changeValueContainer<orxonox::Vector3>(value);     this->type_ = MT_vector3;     } }
234        inline void assignValue(const orxonox::Vector4& value)     { if (this->value_ && this->type_ == MT_vector4)     { this->value_->setValue(value); } else { this->changeValueContainer<orxonox::Vector4>(value);     this->type_ = MT_vector4;     } }
235        inline void assignValue(const orxonox::ColourValue& value) { if (this->value_ && this->type_ == MT_colourvalue) { this->value_->setValue(value); } else { this->changeValueContainer<orxonox::ColourValue>(value); this->type_ = MT_colourvalue; } }
236        inline void assignValue(const orxonox::Quaternion& value)  { if (this->value_ && this->type_ == MT_quaternion)  { this->value_->setValue(value); } else { this->changeValueContainer<orxonox::Quaternion>(value);  this->type_ = MT_quaternion;  } }
237        inline void assignValue(const orxonox::Radian& value)      { if (this->value_ && this->type_ == MT_radian)      { this->value_->setValue(value); } else { this->changeValueContainer<orxonox::Radian>(value);      this->type_ = MT_radian;      } }
238        inline void assignValue(const orxonox::Degree& value)      { if (this->value_ && this->type_ == MT_degree)      { this->value_->setValue(value); } else { this->changeValueContainer<orxonox::Degree>(value);      this->type_ = MT_degree;      } }
239        template <typename T> inline void changeValueContainer(const T& value) { if (this->value_) { delete this->value_; } this->createNewValueContainer<T>(value); }
240        template <typename T>        void createNewValueContainer(const T& value) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }
241
242        MT_ValueBase* value_;
243        MT_Type type_;
244};
245
246_UtilExport inline std::ostream& operator<<(std::ostream& outstream, const MultiType& mt) { if (mt.value_) { mt.value_->toString(outstream); } return outstream; }
247
248template <> inline bool MultiType::isType<char>()                 const { return (this->type_ == MT_char);        }
249template <> inline bool MultiType::isType<unsigned char>()        const { return (this->type_ == MT_uchar);       }
250template <> inline bool MultiType::isType<short>()                const { return (this->type_ == MT_short);       }
251template <> inline bool MultiType::isType<unsigned short>()       const { return (this->type_ == MT_ushort);      }
252template <> inline bool MultiType::isType<int>()                  const { return (this->type_ == MT_int);         }
253template <> inline bool MultiType::isType<unsigned int>()         const { return (this->type_ == MT_uint);        }
254template <> inline bool MultiType::isType<long>()                 const { return (this->type_ == MT_long);        }
255template <> inline bool MultiType::isType<unsigned long>()        const { return (this->type_ == MT_ulong);       }
256template <> inline bool MultiType::isType<long long>()            const { return (this->type_ == MT_longlong);    }
257template <> inline bool MultiType::isType<unsigned long long>()   const { return (this->type_ == MT_ulonglong);   }
258template <> inline bool MultiType::isType<float>()                const { return (this->type_ == MT_float);       }
259template <> inline bool MultiType::isType<double>()               const { return (this->type_ == MT_double);      }
260template <> inline bool MultiType::isType<long double>()          const { return (this->type_ == MT_longdouble);  }
261template <> inline bool MultiType::isType<bool>()                 const { return (this->type_ == MT_bool);        }
262template <> inline bool MultiType::isType<void*>()                const { return (this->type_ == MT_void);        }
263template <> inline bool MultiType::isType<std::string>()          const { return (this->type_ == MT_string);      }
264template <> inline bool MultiType::isType<orxonox::Vector2>()     const { return (this->type_ == MT_vector2);     }
265template <> inline bool MultiType::isType<orxonox::Vector3>()     const { return (this->type_ == MT_vector3);     }
266template <> inline bool MultiType::isType<orxonox::Vector4>()     const { return (this->type_ == MT_vector4);     }
267template <> inline bool MultiType::isType<orxonox::ColourValue>() const { return (this->type_ == MT_colourvalue); }
268template <> inline bool MultiType::isType<orxonox::Quaternion>()  const { return (this->type_ == MT_quaternion);  }
269template <> inline bool MultiType::isType<orxonox::Radian>()      const { return (this->type_ == MT_radian);      }
270template <> inline bool MultiType::isType<orxonox::Degree>()      const { return (this->type_ == MT_degree);      }
271
272template <> inline void MultiType::convert<const std::string&>()          { this->convert<std::string>();          }
273template <> inline void MultiType::convert<const orxonox::Vector2&>()     { this->convert<orxonox::Vector2>();     }
274template <> inline void MultiType::convert<const orxonox::Vector3&>()     { this->convert<orxonox::Vector3>();     }
275template <> inline void MultiType::convert<const orxonox::Vector4&>()     { this->convert<orxonox::Vector4>();     }
276template <> inline void MultiType::convert<const orxonox::ColourValue&>() { this->convert<orxonox::ColourValue>(); }
277template <> inline void MultiType::convert<const orxonox::Quaternion&>()  { this->convert<orxonox::Quaternion>();  }
278template <> inline void MultiType::convert<const orxonox::Radian&>()      { this->convert<orxonox::Radian>();      }
279template <> inline void MultiType::convert<const orxonox::Degree&>()      { this->convert<orxonox::Degree>();      }
280
281template <> void MultiType::createNewValueContainer(const char& value);
282template <> void MultiType::createNewValueContainer(const unsigned char& value);
283template <> void MultiType::createNewValueContainer(const short& value);
284template <> void MultiType::createNewValueContainer(const unsigned short& value);
285template <> void MultiType::createNewValueContainer(const int& value);
286template <> void MultiType::createNewValueContainer(const unsigned int& value);
287template <> void MultiType::createNewValueContainer(const long& value);
288template <> void MultiType::createNewValueContainer(const unsigned long& value);
289template <> void MultiType::createNewValueContainer(const long long& value);
290template <> void MultiType::createNewValueContainer(const unsigned long long& value);
291template <> void MultiType::createNewValueContainer(const float& value);
292template <> void MultiType::createNewValueContainer(const double& value);
293template <> void MultiType::createNewValueContainer(const bool& value);
294template <> void MultiType::createNewValueContainer(const long double& value);
295template <> void MultiType::createNewValueContainer(      void* const& value);
296template <> void MultiType::createNewValueContainer(const std::string& value);
297template <> void MultiType::createNewValueContainer(const orxonox::Vector2& value);
298template <> void MultiType::createNewValueContainer(const orxonox::Vector3& value);
299template <> void MultiType::createNewValueContainer(const orxonox::Vector4& value);
300template <> void MultiType::createNewValueContainer(const orxonox::ColourValue& value);
301template <> void MultiType::createNewValueContainer(const orxonox::Quaternion& value);
302template <> void MultiType::createNewValueContainer(const orxonox::Radian& value);
303template <> void MultiType::createNewValueContainer(const orxonox::Degree& value);
304
305inline void MultiType::setValue(const char* value) { if (this->value_) { this->value_->setValue(std::string(value)); } else { this->createNewValueContainer(std::string(value)); } }
306
307/*
308
309(*) = funktion 2x:
310function(...) : bezieht sich auf aktuellen type
311function<T>(...) : bezieht sich auf type T
312
313constructor(V value) : zuweisung
314(*) operator=(V value) : zuweisung
315(*) setValue(V value) : zuweisung
316
317(*) == != > < <= >= : template
318
319(*) reset() : zurück auf 0 (bzw "")
320setType<T>() : setzt type und macht reset
321convert<T>() : setzt type und konvertiert
322
323(T) : return konvertiert
324
325isType<T>() : return bool
326getType() : return MT_Type
327getTypename() : return string
328
329toString() : return string
330(*) fromString(string value) : konvertiert string
331operator<< : toString()
332
333*/
334
335#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
336#pragma warning(pop)
337#endif
338
339#endif /* _MultiType_H__ */
Note: See TracBrowser for help on using the repository browser.