File: Value

package info (click to toggle)
openscenegraph 2.8.3-5
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 33,968 kB
  • ctags: 30,935
  • sloc: cpp: 287,169; ansic: 9,050; sh: 654; yacc: 548; objc: 374; makefile: 264; lex: 151; perl: 119
file content (436 lines) | stat: -rw-r--r-- 15,116 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * OpenSceneGraph Public License for more details.
*/
//osgIntrospection - Copyright (C) 2005 Marco Jez

#ifndef OSGINTROSPECTION_VALUE_
#define OSGINTROSPECTION_VALUE_

#include <osgIntrospection/Export>
#include <osgIntrospection/Reflection>
#include <osgIntrospection/type_traits>

#include <vector>
#include <memory>
#include <string>

namespace osgIntrospection
{

    class Type;

    class OSGINTROSPECTION_EXPORT Value
    {
    public:
        /// Default constructor. Initializes internal structures
        /// so that the Type returned by getType() is typeof(void),
        /// and the value is empty so that isEmpty() returns true.
        /// Be careful when using empty values, as some operations
        /// on them may throw an exception.
        inline Value();

        /// Direct initialization constructor for void pointers.
        /// Although one of the constructor templates below could
        /// certainly handle void pointers as well, we need to treat 
        /// them separately because void* can't be dereferenced.
        inline Value(void *v);

        /// Direct initialization constructor for const void pointers.
        /// Although one of the constructor templates below could
        /// certainly handle void pointers as well, we need to treat 
        /// them separately because void* can't be dereferenced.
        inline Value(const void *v);

        /// Direct initialization constructor template for non-const
        /// pointers. By initializing an instance of Value through
        /// this constructor, internal structures will be configured
        /// to handle polymorphic types. This means you'll be able to
        /// call getInstanceType() to get the actual type of the
        /// dereferenced value.
        template<typename T> Value(T *v);

        /// Direct initialization constructor template for non-const
        /// pointers. By initializing an instance of Value through
        /// this constructor, internal structures will be configured
        /// to handle polymorphic types. This means you'll be able to
        /// call getInstanceType() to get the actual type of the
        /// dereferenced value.
        template<typename T> Value(const T *v);

        /// Direct initialization constructor template for all types
        /// that are not handled by any of the constructors above.
        /// Calling getInstanceType() on an instance constructed
        /// this way returns the same as getType().
        template<typename T> Value(const T &v);

        /// Copy constructor. The underlying value's type must have
        /// consistent copy semantics.
        inline Value(const Value& copy);

        /// Destructor. Frees internal resources but it does NOT delete
        /// the value held. For example, this function will produce a
        /// memory leak:  void f() { Value v(new int); }
        inline ~Value();

        /// Assignment operator. Behaves like the copy constructor.
        inline Value& operator=(const Value& copy);

        /// Returns whether the value is a pointer and it points to
        /// something whose type is different than void.
        inline bool isTypedPointer() const;

        /// Returns whether this Value is empty.
        inline bool isEmpty() const;

        /// Returns whether the value is a null pointer.
        inline bool isNullPointer() const;

        /// Returns the exact type of the value held.
        inline const Type& getType() const;

        /// If the value is a pointer to a non-void type, this method
        /// returns the actual type of the dereferenced pointer. Please
        /// note it is not the same as getType().getPointedType(),
        /// because the latter would return the non-polymorphic type.
        /// If the value is not a pointer, this method behaves like
        /// getType().
        inline const Type& getInstanceType() const;

        /// Equal to operator.
        bool operator==(const Value& other) const;

        /// Less than or equal to operator.
        bool operator<=(const Value& other) const;
        
        /// Inequality test operator. Returns !operator==(other).
        bool operator!=(const Value& other) const;

        /// Greater than operator. Returns !operator<=(other).
        bool operator>(const Value& other) const;

        /// Less than operator. Returns !operator==(other) && operator<=(other).
        bool operator<(const Value& other) const;
        
        /// Greater than or equal to operator. Returns operator==(other) || !operator<=(other)
        bool operator>=(const Value& other) const;

        /// Tries to convert this instance to a Value of the given type.
        /// The conversion is performed by rendering to a temporary stream
        /// in the source format and trying to read back from the stream
        /// in the destination format. If either the source or destination
        /// types, or both, don't have a ReaderWriter object, the conversion
        /// fails and an exception is thrown. If the conversion can't be
        /// completed for other reasons, other exceptions may be thrown.
        Value convertTo(const Type& outtype) const;

        /// Tries to convert this instance to a Value of the given type.
        /// The conversion is performed by rendering to a temporary stream
        /// in the source format and trying to read back from the stream
        /// in the destination format. If either the source or destination
        /// types, or both, don't have a ReaderWriter object, the conversion
        /// fails and an empty Value is returned.
        /// Please note that unlike convertTo(), this method does not 
        /// intentionally throw any exceptions.
        Value tryConvertTo(const Type& outtype) const;

        /// Tries to get a string representation of the underlying value.
        /// This requires the value's type to have a ReaderWriter object
        /// associated to it. If the conversion can't be completed, an
        /// exception is thrown.
        std::string toString() const;
        std::wstring toWString() const;
        
        /// Swaps the content of this Value with another Value
        void swap(Value& v);


    private:
        // It's good to have friends!
        template<typename T> friend T variant_cast(const Value& v);
        template<typename T> friend bool requires_conversion(const Value& v);
        template<typename T> friend T *extract_raw_data(Value& v);
        template<typename T> friend const T *extract_raw_data(const Value& v);

        // throw an exception if the value is empty
        void check_empty() const;

        // Base class for holding values. Provides a clone() method
        // which must be overriden in descendant classes.
        struct Instance_base  
        { 
            virtual Instance_base *clone() const = 0;
            virtual ~Instance_base() {} 
        };

        // Generic descendant of Instance_base for holding values of
        // type T. Note that values are created on the stack.
        template<typename T>
        struct Instance: Instance_base
        {
            Instance(T data): _data(data) {}
            
            virtual Instance_base *clone() const { return new Instance<T>(*this); }
            virtual ~Instance() {}
            T _data;
            
        protected:
        
            Instance& operator = (const Instance& rhs)
            {
                if (&rhs!=this) 
                {
                    _data = rhs._data;
                }
                return *this;
            }
            
        };

        // Base class for storage of Instance objects. Actually three
        // instances are created: the main instance which keeps the
        // desired value, an additional instance that keeps a reference
        // to that value, and another instance that keeps a const
        // reference to that value. These additional instances are queried 
        // when casting the Value to a reference type.
        struct Instance_box_base
        {
            Instance_box_base()
            :    inst_(0),
                _ref_inst(0),
                _const_ref_inst(0)
            {
            }

            virtual ~Instance_box_base()
            {
                delete inst_;
                delete _ref_inst;
                delete _const_ref_inst;
            }

            // clones the instance box
            virtual Instance_box_base *clone() const = 0;
            // returns the type of the value held
            virtual const Type* type() const = 0;
            // returns the actual pointed type if applicable
            virtual const Type* ptype() const { return 0; }
            // returns whether the data is a null pointer
            virtual bool nullptr() const = 0;

            Instance_base *inst_;
            Instance_base *_ref_inst;
            Instance_base *_const_ref_inst;
        };

        // Generic instance box for non-pointer values.
        template<typename T>
        struct Instance_box: Instance_box_base
        {
            Instance_box(): Instance_box_base(), nullptr_(false) {}

            Instance_box(const T &d, bool nullptr = false)
            :    Instance_box_base(),
                nullptr_(nullptr)
            {
                Instance<T> *vl = new Instance<T>(d);
                inst_ = vl;
                _ref_inst = new Instance<T &>(vl->_data);
                _const_ref_inst = new Instance<const T &>(vl->_data);
            }
            
            virtual Instance_box_base *clone() const
            {
                Instance_box<T> *new_inbox = new Instance_box<T>();

                // ??? this static_cast<> shouldn't be necessary, but the 
                // MSVC++ compiler complains about invalid casting without it!
                Instance<T> *vl = static_cast<Instance<T> *>(inst_->clone());
                
                new_inbox->inst_ = vl;
                new_inbox->_ref_inst = new Instance<T &>(vl->_data);
                new_inbox->_const_ref_inst = new Instance<const T &>(vl->_data);
                new_inbox->nullptr_ = nullptr_;
                return new_inbox;
            }

            virtual const Type* type() const
            {
                return &typeof(T);
            }

            virtual bool nullptr() const
            {
                return nullptr_;
            }

        private:
            bool nullptr_;

            Instance_box& operator = (const Instance_box&) { return *this; }

        };

        // Generic instance box for pointer values. Unlike Instance_box<>, 
        // this struct template provides a ptype() method that unreferences
        // the pointer (T is supposed to be a pointer) and gets its actual
        // type.
        template<typename T>
        struct Ptr_instance_box: Instance_box_base
        {
            Ptr_instance_box(): Instance_box_base() {}

            Ptr_instance_box(const T &d)
            :    Instance_box_base()
            {
                Instance<T> *vl = new Instance<T>(d);
                inst_ = vl;
                _ref_inst = new Instance<T &>(vl->_data);
                _const_ref_inst = new Instance<const T &>(vl->_data);
            }

            virtual Instance_box_base *clone() const
            {
                Ptr_instance_box<T> *new_inbox = new Ptr_instance_box<T>();

                // ??? this static_cast<> shouldn't be necessary, but the 
                // MSVC++ compiler complains about invalid casting without it!
                Instance<T> *vl = static_cast<Instance<T> *>(inst_->clone());
                
                new_inbox->inst_ = vl;
                new_inbox->_ref_inst = new Instance<T &>(vl->_data);
                new_inbox->_const_ref_inst = new Instance<const T &>(vl->_data);
                return new_inbox;
            }

            virtual const Type* type() const
            {
                return &typeof(T);
            }

            virtual const Type* ptype() const
            {
                if (!static_cast<Instance<T> *>(inst_)->_data) return 0;
                return &typeofvalue(*static_cast<Instance<T> *>(inst_)->_data);
            }

            virtual bool nullptr() const
            {
                return static_cast<Instance<T> *>(inst_)->_data == 0;
            }

        };

        Instance_box_base *_inbox;
        const Type* _type;
        const Type* _ptype;
    };

    /// A vector of values.
    typedef std::vector<Value> ValueList;
    
    
    // INLINE METHODS

    inline Value::Value()
    :    _inbox(0),
        _type(&Reflection::type_void()),
        _ptype(0)
    {
    }

    template<typename T> Value::Value(const T &v)
    :    _ptype(0)
    {
        _inbox = new Instance_box<T>(v);
        _type = _inbox->type();
    }

    inline Value::Value(const void *v)
    :    _ptype(0)
    {
        _inbox = new Instance_box<const void *>(v, v == 0);
        _type = _inbox->type();
    }

    inline Value::Value(void *v)
    :    _ptype(0)
    {
        _inbox = new Instance_box<void *>(v, v == 0);
        _type = _inbox->type();
    }

    template<typename T> Value::Value(const T *v)
    {
        _inbox = new Ptr_instance_box<const T *>(v);
        _type = _inbox->type();
        _ptype = _inbox->ptype();
    }

    template<typename T> Value::Value(T *v)
    {
        _inbox = new Ptr_instance_box<T *>(v);
        _type = _inbox->type();
        _ptype = _inbox->ptype();
    }

    inline Value::Value(const Value& copy)
    :    _inbox(copy._inbox? copy._inbox->clone(): 0),
        _type(copy._type),
        _ptype(copy._ptype)
    {
    }

    inline Value& Value::operator=(const Value& copy)
    {
        std::auto_ptr<Instance_box_base> new_inbox(copy._inbox? copy._inbox->clone(): 0);
        delete _inbox;
        _inbox = new_inbox.release();
        _type = copy._type;
        _ptype = copy._ptype;
        return *this;
    }

    inline Value::~Value()
    {
        delete _inbox;
    }

    inline const Type& Value::getType() const 
    { 
        return *_type; 
    }

    inline const Type& Value::getInstanceType() const
    {
        if (_ptype)
            return *_ptype;
        return *_type;
    }

    inline bool Value::isTypedPointer() const
    {
        return _ptype != 0;
    }

    inline bool Value::isEmpty() const
    {
        return _inbox == 0;
    }

    inline bool Value::isNullPointer() const
    {
        return _inbox->nullptr();
    }

}

#endif