source: GTP/trunk/Lib/Geom/OgreStuff/include/OgreAny.h @ 1809

Revision 1809, 9.4 KB checked in by gumbau, 18 years ago (diff)
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) Any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16Any WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://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
43namespace 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
Note: See TracBrowser for help on using the repository browser.