summaryrefslogtreecommitdiff
path: root/src/stable/variant.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/stable/variant.h')
-rw-r--r--src/stable/variant.h236
1 files changed, 236 insertions, 0 deletions
diff --git a/src/stable/variant.h b/src/stable/variant.h
new file mode 100644
index 0000000..45e3339
--- /dev/null
+++ b/src/stable/variant.h
@@ -0,0 +1,236 @@
1/*
2 * Copyright (C) 2007-2011 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#ifndef BU_VARIANT_H
9#define BU_VARIANT_H
10
11//#include <bu/string.h>
12#include <typeinfo>
13// #include <bu/formatter.h>
14
15#ifndef NULL
16#define NULL (0L)
17#endif
18
19#include "bu/exceptionbase.h"
20
21namespace Bu
22{
23 class String;
24 class Formatter;
25 class Variant;
26 /** @cond DEVEL */
27 template<class t> class VariantType;
28
29 class VariantTypeRoot
30 {
31 public:
32 VariantTypeRoot();
33 virtual ~VariantTypeRoot();
34
35 virtual const std::type_info &getType() const=0;
36 virtual VariantTypeRoot *clone() const=0;
37 virtual void format( Bu::Formatter &f ) const=0;
38 };
39
40 template<class t>
41 class VariantType : public VariantTypeRoot
42 {
43 friend class Variant;
44 private:
45 VariantType()
46 {
47 }
48
49 VariantType( const t &d ) :
50 data( d )
51 {
52 }
53
54 VariantType( const VariantType<t> &vt ) :
55 data( vt.data )
56 {
57 }
58
59 virtual ~VariantType()
60 {
61 }
62
63 public:
64 t &getData()
65 {
66 return data;
67 }
68
69 const t &getData() const
70 {
71 return data;
72 }
73
74 virtual void format( Formatter &f ) const
75 {
76 f << data;
77 }
78
79 virtual const std::type_info &getType() const
80 {
81 return typeid( data );
82 }
83
84 VariantType<t> operator=( const t &rhs )
85 {
86 data = rhs;
87
88 return *this;
89 }
90
91 virtual VariantTypeRoot *clone() const
92 {
93 return new VariantType<t>( *this );
94 }
95
96 private:
97 t data;
98 };
99 /** @endcond */
100
101 /**
102 * Store any data type and access it safely. Variant gives you a way to
103 * pass arbitrary data types around without having to worry about what
104 * type a variable is. It allows code to be easily extended and to manage
105 * data without having to know what type it is ahead of time.
106 *
107 * Because of the generic method that this class was implemented it may seem
108 * to have some drawbacks compared to other Variant classes you may have
109 * seen, however it is fairly easy to get it to do just about anything you
110 * may need. It is also very low overhead. On most compilers the class
111 * itself has only 3 words of overhead + the size of the variable you store
112 * in it. And, since many parts of it are templatized they can often be
113 * optimized quite a bit.
114 */
115 class Variant
116 {
117 friend Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v );
118 public:
119 Variant();
120 Variant( const Variant &v );
121 Variant( const char *t );
122 template<class t>
123 Variant( const t &v ) :
124 pCore( new VariantType<t>() )
125 {
126 (*dynamic_cast<VariantType<t> *>(pCore)) = v;
127 }
128 virtual ~Variant();
129
130 Bu::String toString() const;
131 bool isSet() const;
132 const std::type_info &getType() const;
133
134 Variant &operator=( const Variant &rhs );
135
136 template<class t>
137 Variant &operator=( const t &rhs )
138 {
139 if( pCore ) // && pCore->getType() != typeid(t) )
140 {
141 delete pCore;
142 pCore = NULL;
143 }
144 pCore = new VariantType<t>();
145 (*dynamic_cast<VariantType<t> *>(pCore)) = rhs;
146 return *this;
147 }
148
149 template<class t>
150 t &get()
151 {
152 if( !pCore )
153 {
154 throw Bu::ExceptionBase("No data!");
155 }
156 if( pCore->getType() != typeid(t) )
157 {
158 throw Bu::ExceptionBase("Invalid type conversion.");
159 }
160 return dynamic_cast<VariantType<t> *>(pCore)->getData();
161 }
162
163 template<class t>
164 t &get() const
165 {
166 if( !pCore )
167 {
168 throw Bu::ExceptionBase("No data!");
169 }
170 if( pCore->getType() != typeid(t) )
171 {
172 throw Bu::ExceptionBase("Invalid type conversion.");
173 }
174 return dynamic_cast<VariantType<t> *>(pCore)->getData();
175 }
176
177 template<class t>
178 void set( const t &val )
179 {
180 if( pCore && pCore->getType() != typeid(t) )
181 {
182 delete pCore;
183 pCore = NULL;
184 }
185 pCore = new VariantType<t>();
186 (*dynamic_cast<VariantType<t> *>(pCore)) = val;
187 }
188
189 template<class t>
190 bool isType() const
191 {
192 return pCore->getType() == typeid(t);
193 }
194
195 template<class t>
196 operator t()
197 {
198 if( !pCore )
199 {
200 throw Bu::ExceptionBase("No data!");
201 }
202 if( pCore->getType() != typeid(t) )
203 {
204 throw Bu::ExceptionBase("Invalid type conversion.");
205 }
206 return dynamic_cast<VariantType<t> *>(pCore)->getData();
207 }
208
209 template<class t>
210 operator t() const
211 {
212 if( !pCore )
213 {
214 throw Bu::ExceptionBase("No data!");
215 }
216 if( pCore->getType() != typeid(t) )
217 {
218 throw Bu::ExceptionBase("Invalid type conversion.");
219 }
220 return dynamic_cast<VariantType<t> *>(pCore)->getData();
221 }
222
223 private:
224 VariantTypeRoot *pCore;
225 };
226/*
227 template<class t>
228 Bu::Formatter &operator<<( Bu::Formatter &f, const VariantType<t> &vt )
229 {
230 return f << vt.getData;
231 }*/
232
233 Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v );
234};
235
236#endif