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
|
#ifndef GI_OBJECTBASE_HPP
#define GI_OBJECTBASE_HPP
#include <type_traits>
#include <utility>
#include <glib-object.h>
#include <glib.h>
// not mentioned in gir, but needs to be included for some parts
#include <glib/gstdio.h>
namespace gi
{
namespace detail
{
struct GObjectFuncs
{
static void *ref(void *data) { return g_object_ref(data); }
static void *sink(void *data) { return g_object_ref_sink(data); }
static void free(void *data) { g_object_unref(data); }
static void *float_(void *data)
{
g_object_force_floating((GObject *)data);
return g_object_ref(data);
}
};
template<typename Funcs, typename CType = void>
class Wrapper
{
protected:
CType *data_ = nullptr;
static CType *_ref(CType *data) { return data ? Funcs::ref(data) : data; }
static CType *_sink(CType *data) { return data ? Funcs::sink(data) : data; }
static CType *_float(CType *data)
{
return data ? Funcs::float_(data) : data;
}
static void _deleter(CType *&data)
{
if (data)
Funcs::free(data);
}
public:
Wrapper(decltype(data_) d = nullptr, bool own = true, bool sink = true)
: data_(own ? d : (sink ? _sink(d) : _ref(d)))
{}
~Wrapper() { _deleter(data_); }
Wrapper(const Wrapper &other)
{
_deleter(data_);
data_ = _ref(other.data_);
}
Wrapper(Wrapper &&other) noexcept
{
_deleter(data_);
data_ = other.data_;
other.data_ = nullptr;
}
explicit operator bool() const { return (bool)data_; }
Wrapper &operator=(const Wrapper &other)
{
if (&other != this) {
_deleter(data_);
data_ = _ref(other.data_);
}
return *this;
}
Wrapper &operator=(Wrapper &&other) noexcept
{
if (&other != this) {
_deleter(data_);
data_ = other.data_;
other.data_ = nullptr;
}
return *this;
}
bool operator==(const Wrapper &other) const { return data_ == other.data_; }
bool operator==(std::nullptr_t o) const
{
(void)o;
return data_ == o;
}
bool operator!=(const Wrapper &other) const { return data_ != other.data_; }
bool operator!=(std::nullptr_t o) const { return data_ != o; }
CType *gobj_() { return this->data_; }
const CType *gobj_() const { return this->data_; }
};
class wrapper_tag
{};
template<typename CType, typename Funcs, GType GTYPE_>
class WrapperBase : public Wrapper<Funcs>, public wrapper_tag
{
typedef WrapperBase self;
typedef Wrapper<Funcs> super_type;
public:
typedef CType BaseObjectType;
BaseObjectType *gobj_() { return (BaseObjectType *)this->data_; }
const BaseObjectType *gobj_() const
{
return (const BaseObjectType *)this->data_;
}
BaseObjectType *gobj_copy_() const
{
return (BaseObjectType *)self::_ref(this->data_);
}
BaseObjectType *gobj_float_() const
{
return (BaseObjectType *)self::_float(this->data_);
}
BaseObjectType *release_()
{
void *r = nullptr;
std::swap(this->data_, r);
return (BaseObjectType *)r;
}
static GType get_type_() { return GTYPE_; }
GType gobj_type_() { return GTYPE_; }
WrapperBase(BaseObjectType *p = nullptr, bool own = true, bool argout = true)
: super_type(p, own, argout)
{}
WrapperBase(const self &other) = default;
WrapperBase(self &&other) = default;
self &operator=(const self &other) = default;
self &operator=(self &&other) = default;
// always arrange to sink by default nowadays
template<typename Cpp>
static Cpp wrap(
const typename Cpp::BaseObjectType *obj, bool own, bool argout = true)
{
static_assert(sizeof(Cpp) == sizeof(self), "type wrap not supported");
static_assert(std::is_base_of<self, Cpp>::value, "type wrap not supported");
WrapperBase w((self::BaseObjectType *)(obj), own, argout);
return std::move(*static_cast<Cpp *>(&w));
}
};
typedef WrapperBase<void, GObjectFuncs, G_TYPE_NONE> ObjectBase;
// foundation for Variant that will be generated
struct GVariantFuncs
{
static void *ref(void *data) { return g_variant_ref((GVariant *)data); }
static void *sink(void *data) { return g_variant_ref_sink((GVariant *)data); }
static void free(void *data) { g_variant_unref((GVariant *)data); }
static void *float_(void *data) { return data; }
};
typedef WrapperBase<GVariant, GVariantFuncs, G_TYPE_VARIANT> VariantWrapper;
} // namespace detail
} // namespace gi
#endif // GI_OBJECTBASE_HPP
|