root/OpenSceneGraph/trunk/include/osgIntrospection/Value @ 9630

Revision 9630, 14.8 kB (checked in by robert, 6 years ago)

Warnings fixes for VS.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[5328]1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
[4122]2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13//osgIntrospection - Copyright (C) 2005 Marco Jez
14
[3743]15#ifndef OSGINTROSPECTION_VALUE_
16#define OSGINTROSPECTION_VALUE_
17
18#include <osgIntrospection/Export>
19#include <osgIntrospection/Reflection>
[6154]20#include <osgIntrospection/type_traits>
[3743]21
22#include <vector>
23#include <memory>
24#include <string>
25
26namespace osgIntrospection
27{
28
[3906]29    class Type;
[3743]30
[3906]31    class OSGINTROSPECTION_EXPORT Value
32    {
33    public:
34        /// Default constructor. Initializes internal structures
35        /// so that the Type returned by getType() is typeof(void),
36        /// and the value is empty so that isEmpty() returns true.
37        /// Be careful when using empty values, as some operations
38        /// on them may throw an exception.
39        inline Value();
[3743]40
[3906]41        /// Direct initialization constructor for void pointers.
42        /// Although one of the constructor templates below could
43        /// certainly handle void pointers as well, we need to treat
44        /// them separately because void* can't be dereferenced.
45        inline Value(void *v);
[3743]46
[3906]47        /// Direct initialization constructor for const void pointers.
48        /// Although one of the constructor templates below could
49        /// certainly handle void pointers as well, we need to treat
50        /// them separately because void* can't be dereferenced.
51        inline Value(const void *v);
[3743]52
[3906]53        /// Direct initialization constructor template for non-const
54        /// pointers. By initializing an instance of Value through
55        /// this constructor, internal structures will be configured
56        /// to handle polymorphic types. This means you'll be able to
57        /// call getInstanceType() to get the actual type of the
58        /// dereferenced value.
59        template<typename T> Value(T *v);
[3743]60
[3906]61        /// Direct initialization constructor template for non-const
62        /// pointers. By initializing an instance of Value through
63        /// this constructor, internal structures will be configured
64        /// to handle polymorphic types. This means you'll be able to
65        /// call getInstanceType() to get the actual type of the
66        /// dereferenced value.
67        template<typename T> Value(const T *v);
[3743]68
[3906]69        /// Direct initialization constructor template for all types
70        /// that are not handled by any of the constructors above.
71        /// Calling getInstanceType() on an instance constructed
72        /// this way returns the same as getType().
73        template<typename T> Value(const T &v);
[3743]74
[3906]75        /// Copy constructor. The underlying value's type must have
76        /// consistent copy semantics.
[4123]77        inline Value(const Value& copy);
[3743]78
[3906]79        /// Destructor. Frees internal resources but it does NOT delete
80        /// the value held. For example, this function will produce a
81        /// memory leak:  void f() { Value v(new int); }
82        inline ~Value();
[3743]83
[3906]84        /// Assignment operator. Behaves like the copy constructor.
[4123]85        inline Value& operator=(const Value& copy);
[3743]86
[3906]87        /// Returns whether the value is a pointer and it points to
88        /// something whose type is different than void.
89        inline bool isTypedPointer() const;
[3743]90
[3906]91        /// Returns whether this Value is empty.
92        inline bool isEmpty() const;
[3743]93
[3906]94        /// Returns whether the value is a null pointer.
95        inline bool isNullPointer() const;
[3743]96
[3906]97        /// Returns the exact type of the value held.
[4123]98        inline const Type& getType() const;
[3743]99
[3906]100        /// If the value is a pointer to a non-void type, this method
101        /// returns the actual type of the dereferenced pointer. Please
102        /// note it is not the same as getType().getPointedType(),
103        /// because the latter would return the non-polymorphic type.
104        /// If the value is not a pointer, this method behaves like
105        /// getType().
[4123]106        inline const Type& getInstanceType() const;
[3743]107
[3966]108        /// Equal to operator.
[4123]109        bool operator==(const Value& other) const;
[3743]110
[3966]111        /// Less than or equal to operator.
[4123]112        bool operator<=(const Value& other) const;
[3966]113       
[3906]114        /// Inequality test operator. Returns !operator==(other).
[4123]115        bool operator!=(const Value& other) const;
[3743]116
[3966]117        /// Greater than operator. Returns !operator<=(other).
[4123]118        bool operator>(const Value& other) const;
[3966]119
120        /// Less than operator. Returns !operator==(other) && operator<=(other).
[4123]121        bool operator<(const Value& other) const;
[3906]122       
[3966]123        /// Greater than or equal to operator. Returns operator==(other) || !operator<=(other)
[4123]124        bool operator>=(const Value& other) const;
[3966]125
[3906]126        /// Tries to convert this instance to a Value of the given type.
127        /// The conversion is performed by rendering to a temporary stream
128        /// in the source format and trying to read back from the stream
129        /// in the destination format. If either the source or destination
130        /// types, or both, don't have a ReaderWriter object, the conversion
131        /// fails and an exception is thrown. If the conversion can't be
132        /// completed for other reasons, other exceptions may be thrown.
[4123]133        Value convertTo(const Type& outtype) const;
[3743]134
[3906]135        /// Tries to convert this instance to a Value of the given type.
136        /// The conversion is performed by rendering to a temporary stream
137        /// in the source format and trying to read back from the stream
138        /// in the destination format. If either the source or destination
139        /// types, or both, don't have a ReaderWriter object, the conversion
140        /// fails and an empty Value is returned.
141        /// Please note that unlike convertTo(), this method does not
142        /// intentionally throw any exceptions.
[4123]143        Value tryConvertTo(const Type& outtype) const;
[3743]144
[3906]145        /// Tries to get a string representation of the underlying value.
146        /// This requires the value's type to have a ReaderWriter object
147        /// associated to it. If the conversion can't be completed, an
148        /// exception is thrown.
149        std::string toString() const;
[5516]150        std::wstring toWString() const;
[3966]151       
152        /// Swaps the content of this Value with another Value
[4123]153        void swap(Value& v);
[3743]154
155
[3906]156    private:
157        // It's good to have friends!
[4123]158        template<typename T> friend T variant_cast(const Value& v);
159        template<typename T> friend bool requires_conversion(const Value& v);
160        template<typename T> friend T *extract_raw_data(Value& v);
161        template<typename T> friend const T *extract_raw_data(const Value& v);
[3743]162
[3906]163        // throw an exception if the value is empty
164        void check_empty() const;
[3743]165
[3906]166        // Base class for holding values. Provides a clone() method
167        // which must be overriden in descendant classes.
168        struct Instance_base 
169        {
170            virtual Instance_base *clone() const = 0;
171            virtual ~Instance_base() {}
172        };
[3743]173
[3906]174        // Generic descendant of Instance_base for holding values of
175        // type T. Note that values are created on the stack.
176        template<typename T>
177        struct Instance: Instance_base
178        {
[4123]179            Instance(T data): _data(data) {}
[9630]180           
[3906]181            virtual Instance_base *clone() const { return new Instance<T>(*this); }
182            virtual ~Instance() {}
[4123]183            T _data;
[9630]184           
185        protected:
186       
187            Instance& operator = (const Instance& rhs)
188            {
189                if (&rhs!=this)
190                {
191                    _data = rhs._data;
192                }
193                return *this;
194            }
195           
[3906]196        };
[3743]197
[3906]198        // Base class for storage of Instance objects. Actually three
199        // instances are created: the main instance which keeps the
200        // desired value, an additional instance that keeps a reference
201        // to that value, and another instance that keeps a const
202        // reference to that value. These additional instances are queried
203        // when casting the Value to a reference type.
204        struct Instance_box_base
205        {
206            Instance_box_base()
207            :    inst_(0),
[4123]208                _ref_inst(0),
209                _const_ref_inst(0)
[3906]210            {
211            }
[3743]212
[3906]213            virtual ~Instance_box_base()
214            {
215                delete inst_;
[4123]216                delete _ref_inst;
217                delete _const_ref_inst;
[3906]218            }
[3743]219
[3906]220            // clones the instance box
221            virtual Instance_box_base *clone() const = 0;
222            // returns the type of the value held
[4123]223            virtual const Type* type() const = 0;
[3906]224            // returns the actual pointed type if applicable
[4123]225            virtual const Type* ptype() const { return 0; }
[3906]226            // returns whether the data is a null pointer
227            virtual bool nullptr() const = 0;
[3743]228
[3906]229            Instance_base *inst_;
[4123]230            Instance_base *_ref_inst;
231            Instance_base *_const_ref_inst;
[3906]232        };
[3743]233
[3906]234        // Generic instance box for non-pointer values.
235        template<typename T>
236        struct Instance_box: Instance_box_base
237        {
238            Instance_box(): Instance_box_base(), nullptr_(false) {}
[3743]239
[3906]240            Instance_box(const T &d, bool nullptr = false)
241            :    Instance_box_base(),
242                nullptr_(nullptr)
243            {
244                Instance<T> *vl = new Instance<T>(d);
245                inst_ = vl;
[4123]246                _ref_inst = new Instance<T &>(vl->_data);
247                _const_ref_inst = new Instance<const T &>(vl->_data);
[3906]248            }
[9630]249           
[3906]250            virtual Instance_box_base *clone() const
251            {
252                Instance_box<T> *new_inbox = new Instance_box<T>();
[3743]253
[3906]254                // ??? this static_cast<> shouldn't be necessary, but the
255                // MSVC++ compiler complains about invalid casting without it!
256                Instance<T> *vl = static_cast<Instance<T> *>(inst_->clone());
257               
258                new_inbox->inst_ = vl;
[4123]259                new_inbox->_ref_inst = new Instance<T &>(vl->_data);
260                new_inbox->_const_ref_inst = new Instance<const T &>(vl->_data);
[3906]261                new_inbox->nullptr_ = nullptr_;
262                return new_inbox;
263            }
[3743]264
[4123]265            virtual const Type* type() const
[3906]266            {
[6154]267                return &typeof(T);
[3906]268            }
[3743]269
[3906]270            virtual bool nullptr() const
271            {
272                return nullptr_;
273            }
[3743]274
[3906]275        private:
276            bool nullptr_;
[9630]277
278            Instance_box& operator = (const Instance_box&) { return *this; }
279
[3906]280        };
[3743]281
[3906]282        // Generic instance box for pointer values. Unlike Instance_box<>,
283        // this struct template provides a ptype() method that unreferences
284        // the pointer (T is supposed to be a pointer) and gets its actual
285        // type.
286        template<typename T>
287        struct Ptr_instance_box: Instance_box_base
288        {
289            Ptr_instance_box(): Instance_box_base() {}
[3743]290
[3906]291            Ptr_instance_box(const T &d)
292            :    Instance_box_base()
293            {
294                Instance<T> *vl = new Instance<T>(d);
295                inst_ = vl;
[4123]296                _ref_inst = new Instance<T &>(vl->_data);
297                _const_ref_inst = new Instance<const T &>(vl->_data);
[3906]298            }
[3743]299
[3906]300            virtual Instance_box_base *clone() const
301            {
302                Ptr_instance_box<T> *new_inbox = new Ptr_instance_box<T>();
[3743]303
[3906]304                // ??? this static_cast<> shouldn't be necessary, but the
305                // MSVC++ compiler complains about invalid casting without it!
306                Instance<T> *vl = static_cast<Instance<T> *>(inst_->clone());
307               
308                new_inbox->inst_ = vl;
[4123]309                new_inbox->_ref_inst = new Instance<T &>(vl->_data);
310                new_inbox->_const_ref_inst = new Instance<const T &>(vl->_data);
[3906]311                return new_inbox;
312            }
[3743]313
[4123]314            virtual const Type* type() const
[3906]315            {
[6154]316                return &typeof(T);
[3906]317            }
[3743]318
[4123]319            virtual const Type* ptype() const
[3906]320            {
[4123]321                if (!static_cast<Instance<T> *>(inst_)->_data) return 0;
[6368]322                return &typeofvalue(*static_cast<Instance<T> *>(inst_)->_data);
[3906]323            }
[3743]324
[3906]325            virtual bool nullptr() const
326            {
[4123]327                return static_cast<Instance<T> *>(inst_)->_data == 0;
[3906]328            }
[3743]329
[3906]330        };
[3743]331
[4123]332        Instance_box_base *_inbox;
333        const Type* _type;
334        const Type* _ptype;
[3906]335    };
[3743]336
[3906]337    /// A vector of values.
338    typedef std::vector<Value> ValueList;
[3966]339   
340   
[3906]341    // INLINE METHODS
[3743]342
[3906]343    inline Value::Value()
[4123]344    :    _inbox(0),
345        _type(&Reflection::type_void()),
346        _ptype(0)
[3906]347    {
348    }
[3743]349
[3906]350    template<typename T> Value::Value(const T &v)
[4123]351    :    _ptype(0)
[3906]352    {
[4123]353        _inbox = new Instance_box<T>(v);
354        _type = _inbox->type();
[3906]355    }
[3743]356
[3906]357    inline Value::Value(const void *v)
[4123]358    :    _ptype(0)
[3906]359    {
[4123]360        _inbox = new Instance_box<const void *>(v, v == 0);
361        _type = _inbox->type();
[3906]362    }
[3743]363
[3906]364    inline Value::Value(void *v)
[4123]365    :    _ptype(0)
[3906]366    {
[4123]367        _inbox = new Instance_box<void *>(v, v == 0);
368        _type = _inbox->type();
[3906]369    }
[3743]370
[3906]371    template<typename T> Value::Value(const T *v)
372    {
[4123]373        _inbox = new Ptr_instance_box<const T *>(v);
374        _type = _inbox->type();
375        _ptype = _inbox->ptype();
[3906]376    }
[3743]377
[3906]378    template<typename T> Value::Value(T *v)
379    {
[4123]380        _inbox = new Ptr_instance_box<T *>(v);
381        _type = _inbox->type();
382        _ptype = _inbox->ptype();
[3906]383    }
[3743]384
[4123]385    inline Value::Value(const Value& copy)
386    :    _inbox(copy._inbox? copy._inbox->clone(): 0),
387        _type(copy._type),
388        _ptype(copy._ptype)
[3906]389    {
390    }
[3743]391
[4123]392    inline Value& Value::operator=(const Value& copy)
[3906]393    {
[4123]394        std::auto_ptr<Instance_box_base> new_inbox(copy._inbox? copy._inbox->clone(): 0);
395        delete _inbox;
396        _inbox = new_inbox.release();
397        _type = copy._type;
398        _ptype = copy._ptype;
[3906]399        return *this;
400    }
[3743]401
[3906]402    inline Value::~Value()
403    {
[4123]404        delete _inbox;
[3906]405    }
[3743]406
[4123]407    inline const Type& Value::getType() const
[3906]408    {
[4123]409        return *_type;
[3906]410    }
[3743]411
[4123]412    inline const Type& Value::getInstanceType() const
[3906]413    {
[4123]414        if (_ptype)
415            return *_ptype;
416        return *_type;
[3906]417    }
[3743]418
[3906]419    inline bool Value::isTypedPointer() const
420    {
[4123]421        return _ptype != 0;
[3906]422    }
[3743]423
[3906]424    inline bool Value::isEmpty() const
425    {
[4123]426        return _inbox == 0;
[3906]427    }
[3743]428
[3906]429    inline bool Value::isNullPointer() const
430    {
[4123]431        return _inbox->nullptr();
[3906]432    }
[3743]433
434}
435
436#endif
Note: See TracBrowser for help on using the browser.