1 | /*
|
---|
2 | -----------------------------------------------------------------------------
|
---|
3 | This source file is part of OGRE
|
---|
4 | (Object-oriented Graphics Rendering Engine)
|
---|
5 | For the latest info, see http://www.ogre3d.org/
|
---|
6 |
|
---|
7 | Copyright (c) 2000-2005 The OGRE Team
|
---|
8 | Also see acknowledgements in Readme.html
|
---|
9 |
|
---|
10 | This program is free software; you can redistribute it and/or modify it under
|
---|
11 | the terms of the GNU Lesser General Public License as published by the Free Software
|
---|
12 | Foundation; either version 2 of the License, or (at your option) Any later
|
---|
13 | version.
|
---|
14 |
|
---|
15 | This program is distributed in the hope that it will be useful, but WITHOUT
|
---|
16 | Any WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
---|
17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
---|
18 |
|
---|
19 | You should have received a copy of the GNU Lesser General Public License along with
|
---|
20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
---|
21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to
|
---|
22 | http://www.gnu.org/copyleft/lesser.txt.
|
---|
23 | -----------------------------------------------------------------------------
|
---|
24 | */
|
---|
25 | // -- Based on boost::any, original copyright information follows --
|
---|
26 | // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
|
---|
27 | //
|
---|
28 | // Distributed under the Boost Software License, Version 1.0. (See
|
---|
29 | // accompAnying file LICENSE_1_0.txt or copy at
|
---|
30 | // http://www.boost.org/LICENSE_1_0.txt)
|
---|
31 | // -- End original copyright --
|
---|
32 |
|
---|
33 | #ifndef __OGRE_ANY_H__
|
---|
34 | #define __OGRE_ANY_H__
|
---|
35 |
|
---|
36 | #include "OgrePrerequisites.h"
|
---|
37 | #include "OgreException.h"
|
---|
38 | #include "OgreString.h"
|
---|
39 | #include <algorithm>
|
---|
40 | #include <typeinfo>
|
---|
41 |
|
---|
42 |
|
---|
43 | namespace Ogre
|
---|
44 | {
|
---|
45 | /** Variant type that can hold Any other type.
|
---|
46 | */
|
---|
47 | class Any
|
---|
48 | {
|
---|
49 | public: // constructors
|
---|
50 |
|
---|
51 | Any()
|
---|
52 | : mContent(0)
|
---|
53 | {
|
---|
54 | }
|
---|
55 |
|
---|
56 | template<typename ValueType>
|
---|
57 | explicit Any(const ValueType & value)
|
---|
58 | : mContent(new holder<ValueType>(value))
|
---|
59 | {
|
---|
60 | }
|
---|
61 |
|
---|
62 | Any(const Any & other)
|
---|
63 | : mContent(other.mContent ? other.mContent->clone() : 0)
|
---|
64 | {
|
---|
65 | }
|
---|
66 |
|
---|
67 | virtual ~Any()
|
---|
68 | {
|
---|
69 | delete mContent;
|
---|
70 | }
|
---|
71 |
|
---|
72 | public: // modifiers
|
---|
73 |
|
---|
74 | Any& swap(Any & rhs)
|
---|
75 | {
|
---|
76 | std::swap(mContent, rhs.mContent);
|
---|
77 | return *this;
|
---|
78 | }
|
---|
79 |
|
---|
80 | template<typename ValueType>
|
---|
81 | Any& operator=(const ValueType & rhs)
|
---|
82 | {
|
---|
83 | Any(rhs).swap(*this);
|
---|
84 | return *this;
|
---|
85 | }
|
---|
86 |
|
---|
87 | Any & operator=(const Any & rhs)
|
---|
88 | {
|
---|
89 | Any(rhs).swap(*this);
|
---|
90 | return *this;
|
---|
91 | }
|
---|
92 |
|
---|
93 | public: // queries
|
---|
94 |
|
---|
95 | bool isEmpty() const
|
---|
96 | {
|
---|
97 | return !mContent;
|
---|
98 | }
|
---|
99 |
|
---|
100 | const std::type_info& getType() const
|
---|
101 | {
|
---|
102 | return mContent ? mContent->getType() : typeid(void);
|
---|
103 | }
|
---|
104 |
|
---|
105 | inline friend std::ostream& operator <<
|
---|
106 | ( std::ostream& o, const Any& v )
|
---|
107 | {
|
---|
108 | if (v.mContent)
|
---|
109 | v.mContent->writeToStream(o);
|
---|
110 | return o;
|
---|
111 | }
|
---|
112 |
|
---|
113 |
|
---|
114 | protected: // types
|
---|
115 |
|
---|
116 | class placeholder
|
---|
117 | {
|
---|
118 | public: // structors
|
---|
119 |
|
---|
120 | virtual ~placeholder()
|
---|
121 | {
|
---|
122 | }
|
---|
123 |
|
---|
124 | public: // queries
|
---|
125 |
|
---|
126 | virtual const std::type_info& getType() const = 0;
|
---|
127 |
|
---|
128 | virtual placeholder * clone() const = 0;
|
---|
129 |
|
---|
130 | virtual void writeToStream(std::ostream& o) = 0;
|
---|
131 |
|
---|
132 | };
|
---|
133 |
|
---|
134 | template<typename ValueType>
|
---|
135 | class holder : public placeholder
|
---|
136 | {
|
---|
137 | public: // structors
|
---|
138 |
|
---|
139 | holder(const ValueType & value)
|
---|
140 | : held(value)
|
---|
141 | {
|
---|
142 | }
|
---|
143 |
|
---|
144 | public: // queries
|
---|
145 |
|
---|
146 | virtual const std::type_info & getType() const
|
---|
147 | {
|
---|
148 | return typeid(ValueType);
|
---|
149 | }
|
---|
150 |
|
---|
151 | virtual placeholder * clone() const
|
---|
152 | {
|
---|
153 | return new holder(held);
|
---|
154 | }
|
---|
155 |
|
---|
156 | virtual void writeToStream(std::ostream& o)
|
---|
157 | {
|
---|
158 | o << held;
|
---|
159 | }
|
---|
160 |
|
---|
161 |
|
---|
162 | public: // representation
|
---|
163 |
|
---|
164 | ValueType held;
|
---|
165 |
|
---|
166 | };
|
---|
167 |
|
---|
168 |
|
---|
169 |
|
---|
170 | protected: // representation
|
---|
171 | placeholder * mContent;
|
---|
172 |
|
---|
173 | template<typename ValueType>
|
---|
174 | friend ValueType * any_cast(Any *);
|
---|
175 |
|
---|
176 |
|
---|
177 | public:
|
---|
178 |
|
---|
179 | template<typename ValueType>
|
---|
180 | ValueType operator()() const
|
---|
181 | {
|
---|
182 | if (!mContent)
|
---|
183 | {
|
---|
184 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
|
---|
185 | "Bad cast from uninitialised Any",
|
---|
186 | "Any::operator()");
|
---|
187 | }
|
---|
188 | else if(getType() == typeid(ValueType))
|
---|
189 | {
|
---|
190 | return static_cast<Any::holder<ValueType> *>(mContent)->held;
|
---|
191 | }
|
---|
192 | else
|
---|
193 | {
|
---|
194 | StringUtil::StrStreamType str;
|
---|
195 | str << "Bad cast from type '" << getType().name() << "' "
|
---|
196 | << "to '" << typeid(ValueType).name() << "'";
|
---|
197 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
|
---|
198 | str.str(),
|
---|
199 | "Any::operator()");
|
---|
200 | }
|
---|
201 | }
|
---|
202 |
|
---|
203 |
|
---|
204 |
|
---|
205 | };
|
---|
206 |
|
---|
207 |
|
---|
208 | /** Specialised Any class which has built in arithmetic operators, but can
|
---|
209 | hold only types which support operator +,-,* and / .
|
---|
210 | */
|
---|
211 | class AnyNumeric : public Any
|
---|
212 | {
|
---|
213 | public:
|
---|
214 | AnyNumeric()
|
---|
215 | : Any()
|
---|
216 | {
|
---|
217 | }
|
---|
218 |
|
---|
219 | template<typename ValueType>
|
---|
220 | AnyNumeric(const ValueType & value)
|
---|
221 |
|
---|
222 | {
|
---|
223 | mContent = new numholder<ValueType>(value);
|
---|
224 | }
|
---|
225 |
|
---|
226 | AnyNumeric(const AnyNumeric & other)
|
---|
227 | : Any()
|
---|
228 | {
|
---|
229 | mContent = other.mContent ? other.mContent->clone() : 0;
|
---|
230 | }
|
---|
231 | protected:
|
---|
232 | class numplaceholder : public Any::placeholder
|
---|
233 | {
|
---|
234 | public: // structors
|
---|
235 |
|
---|
236 | ~numplaceholder()
|
---|
237 | {
|
---|
238 | }
|
---|
239 | virtual placeholder* add(placeholder* rhs) = 0;
|
---|
240 | virtual placeholder* subtract(placeholder* rhs) = 0;
|
---|
241 | virtual placeholder* multiply(placeholder* rhs) = 0;
|
---|
242 | virtual placeholder* multiply(Real factor) = 0;
|
---|
243 | virtual placeholder* divide(placeholder* rhs) = 0;
|
---|
244 | };
|
---|
245 |
|
---|
246 | template<typename ValueType>
|
---|
247 | class numholder : public numplaceholder
|
---|
248 | {
|
---|
249 | public: // structors
|
---|
250 |
|
---|
251 | numholder(const ValueType & value)
|
---|
252 | : held(value)
|
---|
253 | {
|
---|
254 | }
|
---|
255 |
|
---|
256 | public: // queries
|
---|
257 |
|
---|
258 | virtual const std::type_info & getType() const
|
---|
259 | {
|
---|
260 | return typeid(ValueType);
|
---|
261 | }
|
---|
262 |
|
---|
263 | virtual placeholder * clone() const
|
---|
264 | {
|
---|
265 | return new numholder(held);
|
---|
266 | }
|
---|
267 |
|
---|
268 | virtual placeholder* add(placeholder* rhs)
|
---|
269 | {
|
---|
270 | return new numholder(held + static_cast<numholder*>(rhs)->held);
|
---|
271 | }
|
---|
272 | virtual placeholder* subtract(placeholder* rhs)
|
---|
273 | {
|
---|
274 | return new numholder(held - static_cast<numholder*>(rhs)->held);
|
---|
275 | }
|
---|
276 | virtual placeholder* multiply(placeholder* rhs)
|
---|
277 | {
|
---|
278 | return new numholder(held * static_cast<numholder*>(rhs)->held);
|
---|
279 | }
|
---|
280 | virtual placeholder* multiply(Real factor)
|
---|
281 | {
|
---|
282 | return new numholder(held * factor);
|
---|
283 | }
|
---|
284 | virtual placeholder* divide(placeholder* rhs)
|
---|
285 | {
|
---|
286 | return new numholder(held / static_cast<numholder*>(rhs)->held);
|
---|
287 | }
|
---|
288 | virtual void writeToStream(std::ostream& o)
|
---|
289 | {
|
---|
290 | o << held;
|
---|
291 | }
|
---|
292 |
|
---|
293 | public: // representation
|
---|
294 |
|
---|
295 | ValueType held;
|
---|
296 |
|
---|
297 | };
|
---|
298 |
|
---|
299 | /// Construct from holder
|
---|
300 | AnyNumeric(placeholder* pholder)
|
---|
301 | {
|
---|
302 | mContent = pholder;
|
---|
303 | }
|
---|
304 |
|
---|
305 | public:
|
---|
306 | AnyNumeric & operator=(const AnyNumeric & rhs)
|
---|
307 | {
|
---|
308 | AnyNumeric(rhs).swap(*this);
|
---|
309 | return *this;
|
---|
310 | }
|
---|
311 | AnyNumeric operator+(const AnyNumeric& rhs) const
|
---|
312 | {
|
---|
313 | return AnyNumeric(
|
---|
314 | static_cast<numplaceholder*>(mContent)->add(rhs.mContent));
|
---|
315 | }
|
---|
316 | AnyNumeric operator-(const AnyNumeric& rhs) const
|
---|
317 | {
|
---|
318 | return AnyNumeric(
|
---|
319 | static_cast<numplaceholder*>(mContent)->subtract(rhs.mContent));
|
---|
320 | }
|
---|
321 | AnyNumeric operator*(const AnyNumeric& rhs) const
|
---|
322 | {
|
---|
323 | return AnyNumeric(
|
---|
324 | static_cast<numplaceholder*>(mContent)->multiply(rhs.mContent));
|
---|
325 | }
|
---|
326 | AnyNumeric operator*(Real factor) const
|
---|
327 | {
|
---|
328 | return AnyNumeric(
|
---|
329 | static_cast<numplaceholder*>(mContent)->multiply(factor));
|
---|
330 | }
|
---|
331 | AnyNumeric operator/(const AnyNumeric& rhs) const
|
---|
332 | {
|
---|
333 | return AnyNumeric(
|
---|
334 | static_cast<numplaceholder*>(mContent)->divide(rhs.mContent));
|
---|
335 | }
|
---|
336 | AnyNumeric& operator+=(const AnyNumeric& rhs)
|
---|
337 | {
|
---|
338 | *this = AnyNumeric(
|
---|
339 | static_cast<numplaceholder*>(mContent)->add(rhs.mContent));
|
---|
340 | return *this;
|
---|
341 | }
|
---|
342 | AnyNumeric& operator-=(const AnyNumeric& rhs)
|
---|
343 | {
|
---|
344 | *this = AnyNumeric(
|
---|
345 | static_cast<numplaceholder*>(mContent)->subtract(rhs.mContent));
|
---|
346 | return *this;
|
---|
347 | }
|
---|
348 | AnyNumeric& operator*=(const AnyNumeric& rhs)
|
---|
349 | {
|
---|
350 | *this = AnyNumeric(
|
---|
351 | static_cast<numplaceholder*>(mContent)->multiply(rhs.mContent));
|
---|
352 | return *this;
|
---|
353 | }
|
---|
354 | AnyNumeric& operator/=(const AnyNumeric& rhs)
|
---|
355 | {
|
---|
356 | *this = AnyNumeric(
|
---|
357 | static_cast<numplaceholder*>(mContent)->divide(rhs.mContent));
|
---|
358 | return *this;
|
---|
359 | }
|
---|
360 |
|
---|
361 |
|
---|
362 |
|
---|
363 |
|
---|
364 | };
|
---|
365 |
|
---|
366 |
|
---|
367 | template<typename ValueType>
|
---|
368 | ValueType * any_cast(Any * operand)
|
---|
369 | {
|
---|
370 | return operand && operand->getType() == typeid(ValueType)
|
---|
371 | ? &static_cast<Any::holder<ValueType> *>(operand->mContent)->held
|
---|
372 | : 0;
|
---|
373 | }
|
---|
374 |
|
---|
375 | template<typename ValueType>
|
---|
376 | const ValueType * any_cast(const Any * operand)
|
---|
377 | {
|
---|
378 | return any_cast<ValueType>(const_cast<Any *>(operand));
|
---|
379 | }
|
---|
380 |
|
---|
381 | template<typename ValueType>
|
---|
382 | ValueType any_cast(const Any & operand)
|
---|
383 | {
|
---|
384 | const ValueType * result = any_cast<ValueType>(&operand);
|
---|
385 | if(!result)
|
---|
386 | {
|
---|
387 | StringUtil::StrStreamType str;
|
---|
388 | str << "Bad cast from type '" << operand.getType().name() << "' "
|
---|
389 | << "to '" << typeid(ValueType).name() << "'";
|
---|
390 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
|
---|
391 | str.str(),
|
---|
392 | "Ogre::any_cast");
|
---|
393 | }
|
---|
394 | return *result;
|
---|
395 | }
|
---|
396 |
|
---|
397 |
|
---|
398 | }
|
---|
399 |
|
---|
400 | #endif
|
---|
401 |
|
---|