Wayland++  0.2.6
C++ Bindings for Wayland
wayland-util.hpp
1 /*
2  * Copyright (c) 2014-2019, Nils Christopher Brause, Philipp Kerling
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #ifndef WAYLAND_UTIL_HPP
27 #define WAYLAND_UTIL_HPP
28 
29 #include <algorithm>
30 #include <memory>
31 #include <string>
32 #include <typeinfo>
33 #include <utility>
34 #include <vector>
35 
36 #include <wayland-client-core.h>
37 
38 #define wl_array_for_each_cpp(pos, array) \
39  for ((pos) = static_cast<decltype(pos)>((array)->data); \
40  static_cast<const char*>(pos) < (static_cast<const char*>((array)->data) + (array)->size); \
41  (pos)++)
42 
43 namespace wayland
44 {
45  class proxy_t;
46 
47  class array_t;
48 
49  namespace detail
50  {
59  int check_return_value(int return_value, std::string const &function_name);
60 
66  template<typename native_t>
68  {
69  private:
70  native_t *object = nullptr;
71 
72  protected:
73  basic_wrapper(native_t *object)
74  : object{object}
75  {
76  }
77 
78  public:
80  {
81  }
82 
83  basic_wrapper(basic_wrapper const &other)
84  {
85  *this = other;
86  }
87 
88  basic_wrapper(basic_wrapper &&other) noexcept
89  {
90  *this = std::move(other);
91  }
92 
93  native_t *c_ptr() const
94  {
95  if(!object)
96  throw std::runtime_error("Tried to access empty object");
97  return object;
98  }
99 
100  bool has_object() const
101  {
102  return object;
103  }
104 
105  operator bool() const
106  {
107  return has_object();
108  }
109 
110  operator native_t*() const
111  {
112  return c_ptr();
113  }
114 
115  basic_wrapper& operator=(const basic_wrapper &right)
116  {
117  // Check for self-assignment
118  if(this == &right)
119  return *this;
120  object = right.object;
121  return *this;
122  }
123 
124  basic_wrapper& operator=(basic_wrapper &&right) noexcept
125  {
126  std::swap(object, right.object);
127  return *this;
128  }
129 
130  bool operator==(const basic_wrapper &right) const
131  {
132  return object == right.object;
133  }
134 
135  bool operator!=(const basic_wrapper &right) const
136  {
137  return !(*this == right); // Reuse equals operator
138  }
139  };
140 
146  template<typename native_t>
148  {
149  private:
150  std::shared_ptr<native_t> object;
151 
152  protected:
153  refcounted_wrapper(std::shared_ptr<native_t> const &object)
154  : object{object}
155  {
156  }
157 
158  std::shared_ptr<native_t> ref_ptr() const
159  {
160  return object;
161  }
162 
163  public:
165  {
166  }
167 
169  {
170  *this = other;
171  }
172 
173  refcounted_wrapper(refcounted_wrapper &&other) noexcept
174  {
175  *this = std::move(other);
176  }
177 
178  native_t *c_ptr() const
179  {
180  if(!object)
181  throw std::runtime_error("Tried to access empty object");
182  return object.get();
183  }
184 
185  bool has_object() const
186  {
187  return !!object;
188  }
189 
190  operator bool() const
191  {
192  return has_object();
193  }
194 
195  operator native_t*() const
196  {
197  return c_ptr();
198  }
199 
200  refcounted_wrapper& operator=(const refcounted_wrapper &right)
201  {
202  // Check for self-assignment
203  if(this == &right)
204  return *this;
205  object = right.object;
206  return *this;
207  }
208 
209  refcounted_wrapper& operator=(refcounted_wrapper &&right) noexcept
210  {
211  std::swap(object, right.object);
212  return *this;
213  }
214 
215  bool operator==(const refcounted_wrapper &right) const
216  {
217  return object == right.object;
218  }
219 
220  bool operator!=(const refcounted_wrapper &right) const
221  {
222  return !(*this == right); // Reuse equals operator
223  }
224  };
225 
226  class any
227  {
228  private:
229  class base
230  {
231  public:
232  virtual ~base() { }
233  virtual const std::type_info &type_info() const = 0;
234  virtual base *clone() const = 0;
235  };
236 
237  template <typename T>
238  class derived : public base
239  {
240  private:
241  T val;
242  friend class any;
243 
244  public:
245  derived(const T &t)
246  : val(t) { }
247 
248  const std::type_info &type_info() const override
249  {
250  return typeid(T);
251  }
252 
253  base *clone() const override
254  {
255  return new derived<T>(val);
256  }
257  };
258 
259  base *val;
260 
261  public:
262  any()
263  : val(nullptr) { }
264 
265  any(const any &a)
266  : val(a.val ? a.val->clone() : nullptr) { }
267 
268  template <typename T>
269  any(const T &t)
270  : val(new derived<T>(t)) { }
271 
272  ~any()
273  {
274  delete val;
275  }
276 
277  any &operator=(const any &a)
278  {
279  delete val;
280  val = a.val ? a.val->clone() : nullptr;
281  return *this;
282  }
283 
284  template <typename T>
285  any &operator=(const T &t)
286  {
287  if(val && typeid(T) == val->type_info())
288  static_cast<derived<T>*>(val)->val = t;
289  else
290  {
291  delete val;
292  val = new derived<T>(t);
293  }
294  return *this;
295  }
296 
297  template <typename T>
298  T &get()
299  {
300  if(val && typeid(T) == val->type_info())
301  return static_cast<derived<T>*>(val)->val;
302  throw std::bad_cast();
303  }
304  };
305 
306  template<unsigned int size, int id = 0>
307  class bitfield
308  {
309  uint32_t v;
310  static const uint32_t mask = (1 << size) - 1;
311 
312  public:
313  explicit bitfield(const uint32_t value = 0)
314  : v(value)
315  {
316  }
317 
318  explicit operator uint32_t() const
319  {
320  return v;
321  }
322 
323  operator bool() const
324  {
325  return v;
326  }
327 
328  bitfield(const bitfield<size, id> &b)
329  {
330  operator=(b);
331  }
332 
333  bool operator==(const bitfield<size, id> &b)
334  {
335  return v == b.v;
336  }
337 
338  bool operator!=(const bitfield<size, id> &b)
339  {
340  return !operator==(b);
341  }
342 
343  bitfield<size, id> &operator=(const bitfield<size, id> &b)
344  {
345  v = static_cast<uint32_t>(b);
346  return *this;
347  }
348 
349  bitfield<size, id> operator|(const bitfield<size, id> &b) const
350  {
351  return bitfield<size, id>(v | static_cast<uint32_t>(b));
352  }
353 
354  bitfield<size, id> operator&(const bitfield<size, id> &b) const
355  {
356  return bitfield<size, id>(v & static_cast<uint32_t>(b));
357  }
358 
359  bitfield<size, id> operator^(const bitfield<size, id> &b) const
360  {
361  return bitfield<size, id>((v ^ static_cast<uint32_t>(b)) & mask);
362  }
363 
364  bitfield<size, id> operator~() const
365  {
366  return bitfield<size, id>(~v & mask);
367  }
368 
369  bitfield<size, id> &operator|=(const bitfield<size, id> &b)
370  {
371  operator=(*this | b);
372  return *this;
373  }
374 
375  bitfield<size, id> &operator&=(const bitfield<size, id> &b)
376  {
377  operator=(*this & b);
378  return *this;
379  }
380 
381  bitfield<size, id> &operator^=(const bitfield<size, id> &b)
382  {
383  operator=(*this ^ b);
384  return *this;
385  }
386  };
387 
388  class argument_t
389  {
390  private:
391  bool is_array{false};
392  // Uninitialized argument - only for internal use
393  argument_t();
394 
395  public:
396  wl_argument argument;
397 
398  argument_t(const argument_t &arg);
399  argument_t &operator=(const argument_t &arg);
400  ~argument_t();
401 
402  // handles integers
403  argument_t(uint32_t i);
404  argument_t(int32_t i);
405 
406  // handles wl_fixed_t
407  argument_t(double f);
408 
409  // handles strings
410  argument_t(const std::string &s);
411 
412  // handles objects
413  argument_t(wl_object *o);
414 
415  // handles arrays
416  argument_t(array_t a);
417 
418  // handles null objects, for example for new-id arguments
419  argument_t(std::nullptr_t);
420 
421  // handles file descriptors (have same type as signed integers, so extra function)
422  static argument_t fd(int fileno);
423  };
424  }
425 
426  class array_t
427  {
428  private:
429  wl_array a;
430 
431  array_t(wl_array *arr);
432  void get(wl_array *arr) const;
433 
434  friend class proxy_t;
435  friend class detail::argument_t;
436 
437  public:
438  array_t();
439  array_t(const array_t &arr);
440  array_t(array_t &&arr);
441 
442  template <typename T> array_t(const std::vector<T> &v)
443  {
444  wl_array_init(&a);
445  wl_array_add(&a, v.size()*sizeof(T));
446  T *p;
447  unsigned int c = 0;
448  wl_array_for_each_cpp(p, &a)
449  *p = v.at(c++);
450  }
451 
452  ~array_t();
453  array_t &operator=(const array_t &arr);
454  array_t &operator=(array_t &&arr);
455 
456  template <typename T> array_t &operator=(const std::vector<T> &v)
457  {
458  wl_array_release(&a);
459  wl_array_init(&a);
460  wl_array_add(&a, v.size()*sizeof(T));
461  T *p;
462  unsigned int c = 0;
463  wl_array_for_each_cpp(p, &a)
464  *p = v.at(c++);
465  return *this;
466  }
467 
468  template <typename T> operator std::vector<T>() const
469  {
470  std::vector<T> v;
471  T *p;
472  wl_array_for_each_cpp(p, &a)
473  v.push_back(*p);
474  return v;
475  }
476  };
477 }
478 
479 #endif
wayland::detail::refcounted_wrapper
Refcounted wrapper for C objects.
Definition: wayland-util.hpp:147
wayland::detail::basic_wrapper
Non-refcounted wrapper for C objects.
Definition: wayland-util.hpp:67