objectbase.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #ifndef GI_OBJECTBASE_HPP
  2. #define GI_OBJECTBASE_HPP
  3. #include <type_traits>
  4. #include <utility>
  5. #include <glib-object.h>
  6. #include <glib.h>
  7. namespace gi
  8. {
  9. namespace detail
  10. {
  11. struct GObjectFuncs
  12. {
  13. static void *ref(void *data) { return g_object_ref(data); }
  14. static void *sink(void *data) { return g_object_ref_sink(data); }
  15. static void free(void *data) { g_object_unref(data); }
  16. static void *float_(void *data)
  17. {
  18. g_object_force_floating((GObject *)data);
  19. return g_object_ref(data);
  20. }
  21. };
  22. template<typename Funcs, typename CType = void>
  23. class Wrapper
  24. {
  25. protected:
  26. CType *data_ = nullptr;
  27. static CType *_ref(CType *data) { return data ? Funcs::ref(data) : data; }
  28. static CType *_sink(CType *data) { return data ? Funcs::sink(data) : data; }
  29. static CType *_float(CType *data)
  30. {
  31. return data ? Funcs::float_(data) : data;
  32. }
  33. static void _deleter(CType *&data)
  34. {
  35. if (data)
  36. Funcs::free(data);
  37. }
  38. public:
  39. Wrapper(decltype(data_) d = nullptr, bool own = true, bool sink = true)
  40. : data_(own ? d : (sink ? _sink(d) : _ref(d)))
  41. {}
  42. ~Wrapper() { _deleter(data_); }
  43. Wrapper(const Wrapper &other)
  44. {
  45. _deleter(data_);
  46. data_ = _ref(other.data_);
  47. }
  48. Wrapper(Wrapper &&other) noexcept
  49. {
  50. _deleter(data_);
  51. data_ = other.data_;
  52. other.data_ = nullptr;
  53. }
  54. explicit operator bool() const { return (bool)data_; }
  55. Wrapper &operator=(const Wrapper &other)
  56. {
  57. if (&other != this) {
  58. _deleter(data_);
  59. data_ = _ref(other.data_);
  60. }
  61. return *this;
  62. }
  63. Wrapper &operator=(Wrapper &&other) noexcept
  64. {
  65. if (&other != this) {
  66. _deleter(data_);
  67. data_ = other.data_;
  68. other.data_ = nullptr;
  69. }
  70. return *this;
  71. }
  72. bool operator==(const Wrapper &other) const { return data_ == other.data_; }
  73. bool operator==(std::nullptr_t o) const
  74. {
  75. (void)o;
  76. return data_ == o;
  77. }
  78. bool operator!=(const Wrapper &other) const { return data_ != other.data_; }
  79. bool operator!=(std::nullptr_t o) const { return data_ != o; }
  80. CType *gobj_() { return this->data_; }
  81. const CType *gobj_() const { return this->data_; }
  82. };
  83. class wrapper_tag
  84. {};
  85. template<typename CType, typename Funcs, GType GTYPE_>
  86. class WrapperBase : public Wrapper<Funcs>, public wrapper_tag
  87. {
  88. typedef WrapperBase self;
  89. typedef Wrapper<Funcs> super_type;
  90. public:
  91. typedef CType BaseObjectType;
  92. BaseObjectType *gobj_() { return (BaseObjectType *)this->data_; }
  93. const BaseObjectType *gobj_() const
  94. {
  95. return (const BaseObjectType *)this->data_;
  96. }
  97. BaseObjectType *gobj_copy_() const
  98. {
  99. return (BaseObjectType *)self::_ref(this->data_);
  100. }
  101. BaseObjectType *gobj_float_() const
  102. {
  103. return (BaseObjectType *)self::_float(this->data_);
  104. }
  105. BaseObjectType *release_()
  106. {
  107. void *r = nullptr;
  108. std::swap(this->data_, r);
  109. return (BaseObjectType *)r;
  110. }
  111. static GType get_type_() { return GTYPE_; }
  112. GType gobj_type_() { return GTYPE_; }
  113. WrapperBase(BaseObjectType *p = nullptr, bool own = true, bool argout = true)
  114. : super_type(p, own, argout)
  115. {}
  116. WrapperBase(const self &other) = default;
  117. WrapperBase(self &&other) = default;
  118. self &operator=(const self &other) = default;
  119. self &operator=(self &&other) = default;
  120. // always arrange to sink by default nowadays
  121. template<typename Cpp>
  122. static Cpp wrap(
  123. const typename Cpp::BaseObjectType *obj, bool own, bool argout = true)
  124. {
  125. static_assert(sizeof(Cpp) == sizeof(self), "type wrap not supported");
  126. static_assert(std::is_base_of<self, Cpp>::value, "type wrap not supported");
  127. WrapperBase w((self::BaseObjectType *)(obj), own, argout);
  128. return std::move(*static_cast<Cpp *>(&w));
  129. }
  130. };
  131. typedef WrapperBase<void, GObjectFuncs, G_TYPE_NONE> ObjectBase;
  132. // foundation for Variant that will be generated
  133. struct GVariantFuncs
  134. {
  135. static void *ref(void *data) { return g_variant_ref((GVariant *)data); }
  136. static void *sink(void *data) { return g_variant_ref_sink((GVariant *)data); }
  137. static void free(void *data) { g_variant_unref((GVariant *)data); }
  138. static void *float_(void *data) { return data; }
  139. };
  140. typedef WrapperBase<GVariant, GVariantFuncs, G_TYPE_VARIANT> VariantWrapper;
  141. } // namespace detail
  142. } // namespace gi
  143. #endif // GI_OBJECTBASE_HPP