QtGStreamer 1.2.0
Loading...
Searching...
No Matches
refpointer.h
1/*
2 Copyright (C) 2009-2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
3 Copyright (C) 2010 Collabora Ltd.
4 @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
5
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19#ifndef QGLIB_REFPOINTER_H
20#define QGLIB_REFPOINTER_H
21
22#include "global.h"
23#include "type.h"
24#include "wrap.h"
25#include <cstddef>
26#ifndef Q_MOC_RUN
27#include <boost/type_traits.hpp>
28#endif
29#include <boost/utility/enable_if.hpp>
30#include <QtCore/QHash>
31
32namespace QGlib {
33
34//forward declarations
35class Object;
36class Interface;
37
38
39namespace Private {
40
41template <class T, class X>
42struct RefPointerEqualityCheck {};
43
44template <class T, class X>
45struct RefPointerEqualityCheck<T, RefPointer<X> >
46{
47 static inline bool check(const RefPointer<T> & self, const RefPointer<X> & other)
48 {
49 if (self.m_class && other.m_class) {
50 return self.m_class->m_object == other.m_class->m_object;
51 } else {
52 return self.isNull() && other.isNull();
53 }
54 }
55};
56
57template <class T, class X>
58struct RefPointerEqualityCheck<T, X*>
59{
60 static inline bool check(const RefPointer<T> & self, X* const & other)
61 {
62 return self.m_class ? self.m_class->m_object == other : !other;
63 }
64};
65
66} //namespace Private
67
68
89template <class T>
91{
92public:
93 inline RefPointer();
94 inline ~RefPointer();
95
97 explicit inline RefPointer(T *cppClass);
98
99 template <class X>
100 inline RefPointer(const RefPointer<X> & other);
101 inline RefPointer(const RefPointer<T> & other);
102
103 template <class X>
104 inline RefPointer<T> & operator=(const RefPointer<X> & other);
105 inline RefPointer<T> & operator=(const RefPointer<T> & other);
106
120 template <class X>
121 bool operator==(const X & other) const;
122 template <class X>
123 bool operator!=(const X & other) const;
124
127 void clear();
128
129 inline bool isNull() const;
130 inline bool operator!() const;
131 inline T *operator->() const;
132
139 inline operator typename T::CType*() const;
140
145 static RefPointer<T> wrap(typename T::CType *nativePtr, bool increaseRef = true);
146
148 template <class X>
150
164 template <class X>
166
167private:
168 template <class X> friend class RefPointer;
169 template <class X, class Y> friend struct Private::RefPointerEqualityCheck;
170
171 template <class X>
172 void assign(const RefPointer<X> & other);
173
174 T *m_class;
175};
176
181class QTGLIB_EXPORT RefCountedObject
182{
183public:
184 virtual ~RefCountedObject() {}
185
186protected:
187 template <class T> friend class RefPointer;
188 template <class T, class X> friend struct Private::RefPointerEqualityCheck;
189
190 virtual void ref(bool increaseRef) = 0;
191 virtual void unref() = 0;
192
193 template <class T>
194 inline T* object() const;
195
196 void *m_object;
197};
198
199template <class T>
200inline T* RefCountedObject::object() const
201{
202 return static_cast<T* const>(m_object);
203}
204
205
206template <class T>
207inline RefPointer<T>::RefPointer()
208 : m_class(NULL)
209{
210}
211
212template <class T>
213inline RefPointer<T>::~RefPointer()
214{
215 clear();
216}
217
218template <class T>
219inline RefPointer<T>::RefPointer(T *cppClass)
220 : m_class(cppClass)
221{
222 static_cast<RefCountedObject*>(m_class)->ref(true);
223}
224
225template <class T>
226template <class X>
227inline RefPointer<T>::RefPointer(const RefPointer<X> & other)
228 : m_class(NULL)
229{
230 assign(other);
231}
232
233template <class T>
234inline RefPointer<T>::RefPointer(const RefPointer<T> & other)
235 : m_class(NULL)
236{
237 assign(other);
238}
239
240template <class T>
241template <class X>
242inline RefPointer<T> & RefPointer<T>::operator=(const RefPointer<X> & other)
243{
244 clear();
245 assign(other);
246 return *this;
247}
248
249template <class T>
250inline RefPointer<T> & RefPointer<T>::operator=(const RefPointer<T> & other)
251{
252 clear();
253 assign(other);
254 return *this;
255}
256
257template <class T>
258template <class X>
259void RefPointer<T>::assign(const RefPointer<X> & other)
260{
261 //T should be a base class of X
262 QGLIB_STATIC_ASSERT((boost::is_base_of<T, X>::value),
263 "Cannot implicitly cast a RefPointer down the hierarchy");
264
265 if (!other.isNull()) {
266 m_class = static_cast<T*>(other.m_class);
267 static_cast<RefCountedObject*>(m_class)->ref(true);
268 }
269}
270
271template <class T>
272template <class X>
273bool RefPointer<T>::operator==(const X & other) const
274{
275 return Private::RefPointerEqualityCheck<T, X>::check(*this, other);
276}
277
278template <class T>
279template <class X>
280bool RefPointer<T>::operator!=(const X & other) const
281{
282 return !Private::RefPointerEqualityCheck<T, X>::check(*this, other);
283}
284
288template <class T, class X>
289//use this function only if X is a pointer and is NOT the same as T::CType*, otherwise
290//it is ambiguous with RefPointer::operator==() and the built-in operator== for pointers.
291typename boost::enable_if_c<
292 boost::is_pointer<X>::value &&
293 !boost::is_same<X, typename boost::add_pointer<typename T::CType>::type>::value,
294 bool
295>::type
296operator==(const X & other, const RefPointer<T> & self)
297{
298 return Private::RefPointerEqualityCheck<T, X>::check(self, other);
299}
300
304template <class T, class X>
305//use this function only if X is a pointer and is NOT the same as T::CType*, otherwise
306//it is ambiguous with RefPointer::operator!=() and the built-in operator!= for pointers.
307typename boost::enable_if_c<
308 boost::is_pointer<X>::value &&
309 !boost::is_same<X, typename boost::add_pointer<typename T::CType>::type>::value,
310 bool
311>::type
312operator!=(const X & other, const RefPointer<T> & self)
313{
314 return !Private::RefPointerEqualityCheck<T, X>::check(self, other);
315}
316
317template <class T>
319{
320 if (!isNull()) {
321 static_cast<RefCountedObject*>(m_class)->unref(); //this may delete m_class at this point
322 m_class = NULL;
323 }
324}
325
326//static
327template <class T>
328RefPointer<T> RefPointer<T>::wrap(typename T::CType *nativePtr, bool increaseRef)
329{
330 RefPointer<T> ptr;
331 if (nativePtr != NULL) {
332 RefCountedObject *cppObj = WrapImpl<T>::wrap(nativePtr);
333 cppObj->ref(increaseRef);
334 ptr.m_class = dynamic_cast<T*>(cppObj);
335 Q_ASSERT(ptr.m_class);
336 }
337 return ptr;
338}
339
340template <class T>
341inline bool RefPointer<T>::isNull() const
342{
343 return m_class == NULL;
344}
345
346template <class T>
347inline bool RefPointer<T>::operator!() const
348{
349 return m_class == NULL;
350}
351
352template <class T>
353inline T *RefPointer<T>::operator->() const
354{
355 Q_ASSERT_X(!isNull(), "RefPointer::operator->() const",
356 "Attempted to dereference a null pointer");
357 return m_class;
358}
359
360template <class T>
361inline RefPointer<T>::operator typename T::CType*() const
362{
363 return m_class ? static_cast<RefCountedObject*>(m_class)->object<typename T::CType>() : NULL;
364}
365
366template <class T>
367template <class X>
369{
370 RefPointer<X> result;
371 if (m_class) {
372 static_cast<RefCountedObject*>(m_class)->ref(true);
373 result.m_class = static_cast<X*>(m_class);
374 }
375 return result;
376}
377
378
379namespace Private {
380
381template <typename T, typename X, typename Enable = void>
382struct IfaceDynamicCastImpl
383{
384 static inline X *doCast(typename X::CType *obj)
385 {
386 Q_UNUSED(obj);
387 return NULL;
388 }
389};
390
391//this version is compiled if X is an interface and T is an object,
392//i.e. we are dynamically casting from an object to an interface.
393template <typename T, typename X>
394struct IfaceDynamicCastImpl<T, X,
395 typename boost::enable_if_c<
396 //to check if something is an interface, we need to also verify that it does
397 //not inherit Object, since derived object classes may also derive from interfaces.
398 (boost::is_base_of<Interface, X>::value &&
399 !boost::is_base_of<Object, X>::value &&
400 boost::is_base_of<Object, T>::value)
401 >::type
402 >
403{
404 static inline X *doCast(typename X::CType *obj)
405 {
406 X *targetClass = NULL;
407
408 //Check that instanceType implements (isA) the interface
409 //and if it does, return a wrapper for that interface.
410 if (Type::fromInstance(obj).isA(GetType<X>()))
411 {
412 targetClass = dynamic_cast<X*>(Private::wrapInterface(GetType<X>(), obj));
413 Q_ASSERT(targetClass);
414 }
415
416 return targetClass;
417 }
418};
419
420//this version is compiled if T is an interface,
421//i.e. we are dynamically casting from an interface to either an object or another interface.
422template <typename T, typename X>
423struct IfaceDynamicCastImpl<T, X,
424 typename boost::enable_if_c<
425 //to check if something is an interface, we need to also verify that it does
426 //not inherit Object, since derived object classes may also derive from interfaces.
427 (boost::is_base_of<Interface, T>::value &&
428 !boost::is_base_of<Object, T>::value)
429 >::type
430 >
431{
432 static inline X *doCast(typename X::CType *obj)
433 {
434 //get the instance type and try to create (or rather fetch from the GObject qdata)
435 //the C++ wrapper class for this type of object.
436 RefCountedObject *cppClass = Private::wrapObject(obj);
437
438 //attempt to cast it to X
439 X *targetClass = dynamic_cast<X*>(cppClass);
440
441 if (!targetClass) {
442 //Cast failed. This either means that X is something that our instance is not
443 //or that X is another interface that is not inherited by the wrapper class
444 //for this instance type, but it is possible that our instance actually
445 //implements it, so let's check it.
446 if (boost::is_base_of<Interface, X>::value &&
447 !boost::is_base_of<Object, X>::value &&
448 Type::fromInstance(obj).isA(GetType<X>()))
449 {
450 targetClass = dynamic_cast<X*>(Private::wrapInterface(GetType<X>(), obj));
451 Q_ASSERT(targetClass);
452 }
453 }
454
455 return targetClass;
456 }
457};
458
459} //namespace Private
460
461
462template <class T>
463template <class X>
465{
466 RefPointer<X> result;
467 if (m_class) {
468 X *targetClass = dynamic_cast<X*>(m_class);
469 if (!targetClass) {
470 //in case either X or T is an interface, we need to do some extra checks.
471 //this is a template to optimize the compiled code depending on what X and T are.
472 typename X::CType *obj = static_cast<RefCountedObject*>(m_class)->object<typename X::CType>();
473 targetClass = Private::IfaceDynamicCastImpl<T, X>::doCast(obj);
474 }
475
476 if (targetClass) {
477 static_cast<RefCountedObject*>(targetClass)->ref(true);
478 result.m_class = targetClass;
479 }
480 }
481
482 return result;
483}
484
485// trick GetType to return the same type for GetType<T>() and GetType< RefPointer<T> >()
486template <class T>
487struct GetTypeImpl< RefPointer<T> >
488{
489 inline operator Type() { return GetType<T>(); }
490};
491
493template <typename T>
494inline uint qHash(const RefPointer<T> & ptr)
495{
496 return qHash(static_cast<typename T::CType*>(ptr));
497}
498
499} //namespace QGlib
500
501#endif
Base class for all the reference-counted object wrappers.
Definition refpointer.h:182
Smart pointer class for working with wrapper classes that support reference counting.
Definition refpointer.h:91
RefPointer< X > staticCast() const
Definition refpointer.h:368
RefPointer(T *cppClass)
Definition refpointer.h:219
RefPointer< X > dynamicCast() const
Definition refpointer.h:464
boost::enable_if_c< boost::is_pointer< X >::value &&!boost::is_same< X, typenameboost::add_pointer< typenameT::CType >::type >::value, bool >::type operator==(const X &other, const RefPointer< T > &self)
Definition refpointer.h:296
static RefPointer< T > wrap(typename T::CType *nativePtr, bool increaseRef=true)
Definition refpointer.h:328
bool operator==(const X &other) const
Definition refpointer.h:273
boost::enable_if_c< boost::is_pointer< X >::value &&!boost::is_same< X, typenameboost::add_pointer< typenameT::CType >::type >::value, bool >::type operator!=(const X &other, const RefPointer< T > &self)
Definition refpointer.h:312
bool operator!=(const X &other) const
Definition refpointer.h:280
Wrapper class for GType.
Definition type.h:64
Wrappers for Glib and GObject classes.