summaryrefslogtreecommitdiff
path: root/src/variant.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/variant.h')
-rw-r--r--src/variant.h184
1 files changed, 184 insertions, 0 deletions
diff --git a/src/variant.h b/src/variant.h
new file mode 100644
index 0000000..889df88
--- /dev/null
+++ b/src/variant.h
@@ -0,0 +1,184 @@
1#ifndef BU_VARIANT_H
2#define BU_VARIANT_H
3
4#include <bu/fstring.h>
5#include <typeinfo>
6#include <bu/membuf.h>
7#include <bu/formatter.h>
8
9namespace Bu
10{
11 class Formatter;
12 class Variant;
13 template<class t> class VariantType;
14
15 class VariantTypeRoot
16 {
17 public:
18 VariantTypeRoot();
19 virtual ~VariantTypeRoot();
20
21 virtual Bu::FString toString() const=0;
22 virtual const std::type_info &getType() const=0;
23 virtual VariantTypeRoot *clone() const=0;
24 };
25
26 template<class t>
27 class VariantType : public VariantTypeRoot
28 {
29 friend class Variant;
30 private:
31 VariantType()
32 {
33 }
34
35 VariantType( const t &d ) :
36 data( d )
37 {
38 }
39
40 VariantType( const VariantType<t> &vt ) :
41 data( vt.data )
42 {
43 }
44
45 virtual ~VariantType()
46 {
47 }
48
49 public:
50 t &getData()
51 {
52 return data;
53 }
54
55 t &getData() const
56 {
57 return data;
58 }
59
60 virtual Bu::FString toString() const
61 {
62 MemBuf mb;
63 Formatter f( mb );
64 f << data;
65 return mb.getString();
66 }
67
68 virtual const std::type_info &getType() const
69 {
70 return typeid( data );
71 }
72
73 VariantType<t> operator=( const t &rhs )
74 {
75 data = rhs;
76
77 return *this;
78 }
79
80 virtual VariantTypeRoot *clone() const
81 {
82 return new VariantType<t>( *this );
83 }
84
85 private:
86 t data;
87 };
88
89 class Variant
90 {
91 public:
92 Variant();
93 virtual ~Variant();
94
95 bool isSet();
96 Bu::FString toString() const;
97 const std::type_info &getType() const;
98
99 Variant &operator=( const Variant &rhs );
100
101 template<class t>
102 Variant &operator=( const t &rhs )
103 {
104 if( pCore && pCore->getType() != typeid(t) )
105 {
106 delete pCore;
107 pCore = NULL;
108 }
109 pCore = new VariantType<t>();
110 (*dynamic_cast<VariantType<t> *>(pCore)) = rhs;
111 return *this;
112 }
113
114 template<class t>
115 t &get()
116 {
117 if( !pCore )
118 {
119 throw Bu::ExceptionBase("No data!");
120 }
121 if( pCore->getType() != typeid(t) )
122 {
123 throw Bu::ExceptionBase("Invalid type conversion.");
124 }
125 return dynamic_cast<VariantType<t> *>(pCore)->getData();
126 }
127
128 template<class t>
129 void set( const t &val )
130 {
131 if( pCore && pCore->getType() != typeid(t) )
132 {
133 delete pCore;
134 pCore = NULL;
135 }
136 pCore = new VariantType<t>();
137 (*dynamic_cast<VariantType<t> *>(pCore)) = val;
138 }
139
140 template<class t>
141 operator t()
142 {
143 if( !pCore )
144 {
145 throw Bu::ExceptionBase("No data!");
146 }
147 if( pCore->getType() != typeid(t) )
148 {
149 throw Bu::ExceptionBase("Invalid type conversion.");
150 }
151 return dynamic_cast<VariantType<t> *>(pCore)->getData();
152 }
153
154 template<class t>
155 operator t() const
156 {
157 if( !pCore )
158 {
159 throw Bu::ExceptionBase("No data!");
160 }
161 if( pCore->getType() != typeid(t) )
162 {
163 throw Bu::ExceptionBase("Invalid type conversion.");
164 }
165 return dynamic_cast<VariantType<t> *>(pCore)->getData();
166 }
167
168 private:
169 VariantTypeRoot *pCore;
170 };
171
172 template<class t>
173 Bu::Formatter &operator<<( Bu::Formatter &f, const VariantType<t> &vt )
174 {
175 return f << vt.toString();
176 }
177
178 Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v );
179
180 template<> Bu::FString VariantType<int>::toString() const;
181 template<> Bu::FString VariantType<bool>::toString() const;
182};
183
184#endif