aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tests/variant.cpp45
-rw-r--r--src/variant.cpp77
-rw-r--r--src/variant.h184
3 files changed, 306 insertions, 0 deletions
diff --git a/src/tests/variant.cpp b/src/tests/variant.cpp
new file mode 100644
index 0000000..a0ac1f2
--- /dev/null
+++ b/src/tests/variant.cpp
@@ -0,0 +1,45 @@
1#include <bu/sio.h>
2#include <bu/variant.h>
3#include <bu/list.h>
4
5using namespace Bu;
6
7Variant getThing( int i )
8{
9 Variant v;
10 switch( i )
11 {
12 case 0:
13 v = 45;
14 break;
15
16 case 1:
17 v = true;
18 break;
19
20 case 2:
21 v = List<int>(5).append(10).append(15);
22 break;
23 }
24
25 return v;
26}
27
28int main()
29{
30 Variant a;
31 Variant b;
32 Variant c;
33
34 a = getThing( 0 );
35 b = getThing( 1 );
36 c = getThing( 2 );
37
38 sio << "a = " << a << " or " << (int)a << sio.nl
39 << "b = " << b << " or " << b.toString() << sio.nl
40 << "c = " << c << " or " << c.toString() << sio.nl
41 << sio.nl;
42
43 return 0;
44}
45
diff --git a/src/variant.cpp b/src/variant.cpp
new file mode 100644
index 0000000..95eea88
--- /dev/null
+++ b/src/variant.cpp
@@ -0,0 +1,77 @@
1#include "bu/variant.h"
2
3namespace Bu
4{
5 Formatter &operator<<( Formatter &f, const FString &s );
6};
7
8Bu::VariantTypeRoot::VariantTypeRoot()
9{
10}
11
12Bu::VariantTypeRoot::~VariantTypeRoot()
13{
14}
15
16Bu::Variant::Variant() :
17 pCore( NULL )
18{
19}
20
21Bu::Variant::~Variant()
22{
23}
24
25bool Bu::Variant::isSet()
26{
27 return pCore != NULL;
28}
29
30Bu::FString Bu::Variant::toString() const
31{
32 if( !pCore )
33 return "***NO DATA***";
34 return pCore->toString();
35}
36
37const std::type_info &Bu::Variant::getType() const
38{
39 if( !pCore )
40 {
41 throw Bu::ExceptionBase("No data!");
42 }
43 return pCore->getType();
44}
45
46Bu::Variant &Bu::Variant::operator=( const Bu::Variant &rhs )
47{
48 if( pCore )
49 {
50 delete pCore;
51 pCore = NULL;
52 }
53 if( rhs.pCore )
54 {
55 pCore = rhs.pCore->clone();
56 }
57
58 return *this;
59}
60
61Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Variant &v )
62{
63 return f << v.toString();
64}
65
66template<> Bu::FString Bu::VariantType<int>::toString() const
67{
68 Bu::FString s;
69 s.format("%d", data );
70 return s;
71}
72
73template<> Bu::FString Bu::VariantType<bool>::toString() const
74{
75 return data?"true":"false";
76}
77
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