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

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

Warnings fixes for VS.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
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
15#ifndef OSGINTROSPECTION_VALUE_
16#define OSGINTROSPECTION_VALUE_
17
18#include <osgIntrospection/Export>
19#include <osgIntrospection/Reflection>
20#include <osgIntrospection/type_traits>
21
22#include <vector>
23#include <memory>
24#include <string>
25
26namespace osgIntrospection
27{
28
29    class Type;
30
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();
40
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);
46
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);
52
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);
60
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);
68
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);
74
75        /// Copy constructor. The underlying value's type must have
76        /// consistent copy semantics.
77        inline Value(const Value& copy);
78
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();
83
84        /// Assignment operator. Behaves like the copy constructor.
85        inline Value& operator=(const Value& copy);
86
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;
90
91        /// Returns whether this Value is empty.
92        inline bool isEmpty() const;
93
94        /// Returns whether the value is a null pointer.
95        inline bool isNullPointer() const;
96
97        /// Returns the exact type of the value held.
98        inline const Type& getType() const;
99
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().
106        inline const Type& getInstanceType() const;
107
108        /// Equal to operator.
109        bool operator==(const Value& other) const;
110
111        /// Less than or equal to operator.
112        bool operator<=(const Value& other) const;
113       
114        /// Inequality test operator. Returns !operator==(other).
115        bool operator!=(const Value& other) const;
116
117        /// Greater than operator. Returns !operator<=(other).
118        bool operator>(const Value& other) const;
119
120        /// Less than operator. Returns !operator==(other) && operator<=(other).
121        bool operator<(const Value& other) const;
122       
123        /// Greater than or equal to operator. Returns operator==(other) || !operator<=(other)
124        bool operator>=(const Value& other) const;
125
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.
133        Value convertTo(const Type& outtype) const;
134
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.
143        Value tryConvertTo(const Type& outtype) const;
144
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;
150        std::wstring toWString() const;
151       
152        /// Swaps the content of this Value with another Value
153        void swap(Value& v);
154
155
156    private:
157        // It's good to have friends!
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);
162
163        // throw an exception if the value is empty
164        void check_empty() const;
165
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        };
173
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        {
179            Instance(T data): _data(data) {}
180           
181            virtual Instance_base *clone() const { return new Instance<T>(*this); }
182            virtual ~Instance() {}
183            T _data;
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           
196        };
197
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),
208                _ref_inst(0),
209                _const_ref_inst(0)
210            {
211            }
212
213            virtual ~Instance_box_base()
214            {
215                delete inst_;
216                delete _ref_inst;
217                delete _const_ref_inst;
218            }
219
220            // clones the instance box
221            virtual Instance_box_base *clone() const = 0;
222            // returns the type of the value held
223            virtual const Type* type() const = 0;
224            // returns the actual pointed type if applicable
225            virtual const Type* ptype() const { return 0; }
226            // returns whether the data is a null pointer
227            virtual bool nullptr() const = 0;
228
229            Instance_base *inst_;
230            Instance_base *_ref_inst;
231            Instance_base *_const_ref_inst;
232        };
233
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) {}
239
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;
246                _ref_inst = new Instance<T &>(vl->_data);
247                _const_ref_inst = new Instance<const T &>(vl->_data);
248            }
249           
250            virtual Instance_box_base *clone() const
251            {
252                Instance_box<T> *new_inbox = new Instance_box<T>();
253
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;
259                new_inbox->_ref_inst = new Instance<T &>(vl->_data);
260                new_inbox->_const_ref_inst = new Instance<const T &>(vl->_data);
261                new_inbox->nullptr_ = nullptr_;
262                return new_inbox;
263            }
264
265            virtual const Type* type() const
266            {
267                return &typeof(T);
268            }
269
270            virtual bool nullptr() const
271            {
272                return nullptr_;
273            }
274
275        private:
276            bool nullptr_;
277
278            Instance_box& operator = (const Instance_box&) { return *this; }
279
280        };
281
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() {}
290
291            Ptr_instance_box(const T &d)
292            :    Instance_box_base()
293            {
294                Instance<T> *vl = new Instance<T>(d);
295                inst_ = vl;
296                _ref_inst = new Instance<T &>(vl->_data);
297                _const_ref_inst = new Instance<const T &>(vl->_data);
298            }
299
300            virtual Instance_box_base *clone() const
301            {
302                Ptr_instance_box<T> *new_inbox = new Ptr_instance_box<T>();
303
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;
309                new_inbox->_ref_inst = new Instance<T &>(vl->_data);
310                new_inbox->_const_ref_inst = new Instance<const T &>(vl->_data);
311                return new_inbox;
312            }
313
314            virtual const Type* type() const
315            {
316                return &typeof(T);
317            }
318
319            virtual const Type* ptype() const
320            {
321                if (!static_cast<Instance<T> *>(inst_)->_data) return 0;
322                return &typeofvalue(*static_cast<Instance<T> *>(inst_)->_data);
323            }
324
325            virtual bool nullptr() const
326            {
327                return static_cast<Instance<T> *>(inst_)->_data == 0;
328            }
329
330        };
331
332        Instance_box_base *_inbox;
333        const Type* _type;
334        const Type* _ptype;
335    };
336
337    /// A vector of values.
338    typedef std::vector<Value> ValueList;
339   
340   
341    // INLINE METHODS
342
343    inline Value::Value()
344    :    _inbox(0),
345        _type(&Reflection::type_void()),
346        _ptype(0)
347    {
348    }
349
350    template<typename T> Value::Value(const T &v)
351    :    _ptype(0)
352    {
353        _inbox = new Instance_box<T>(v);
354        _type = _inbox->type();
355    }
356
357    inline Value::Value(const void *v)
358    :    _ptype(0)
359    {
360        _inbox = new Instance_box<const void *>(v, v == 0);
361        _type = _inbox->type();
362    }
363
364    inline Value::Value(void *v)
365    :    _ptype(0)
366    {
367        _inbox = new Instance_box<void *>(v, v == 0);
368        _type = _inbox->type();
369    }
370
371    template<typename T> Value::Value(const T *v)
372    {
373        _inbox = new Ptr_instance_box<const T *>(v);
374        _type = _inbox->type();
375        _ptype = _inbox->ptype();
376    }
377
378    template<typename T> Value::Value(T *v)
379    {
380        _inbox = new Ptr_instance_box<T *>(v);
381        _type = _inbox->type();
382        _ptype = _inbox->ptype();
383    }
384
385    inline Value::Value(const Value& copy)
386    :    _inbox(copy._inbox? copy._inbox->clone(): 0),
387        _type(copy._type),
388        _ptype(copy._ptype)
389    {
390    }
391
392    inline Value& Value::operator=(const Value& copy)
393    {
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;
399        return *this;
400    }
401
402    inline Value::~Value()
403    {
404        delete _inbox;
405    }
406
407    inline const Type& Value::getType() const
408    {
409        return *_type;
410    }
411
412    inline const Type& Value::getInstanceType() const
413    {
414        if (_ptype)
415            return *_ptype;
416        return *_type;
417    }
418
419    inline bool Value::isTypedPointer() const
420    {
421        return _ptype != 0;
422    }
423
424    inline bool Value::isEmpty() const
425    {
426        return _inbox == 0;
427    }
428
429    inline bool Value::isNullPointer() const
430    {
431        return _inbox->nullptr();
432    }
433
434}
435
436#endif
Note: See TracBrowser for help on using the browser.