File: objectbase.hpp

package info (click to toggle)
cppgir 2.0%2Bgit20240928.c8bb1c6%2Breally2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,228 kB
  • sloc: cpp: 14,307; ansic: 339; makefile: 11; sh: 9
file content (177 lines) | stat: -rw-r--r-- 4,362 bytes parent folder | download | duplicates (2)
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