Wayland++  0.2.8
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 <stdexcept>
32 #include <string>
33 #include <typeinfo>
34 #include <utility>
35 #include <vector>
36 
37 #include <wayland-client-core.h>
38 
39 #define wl_array_for_each_cpp(pos, array) \
40  for ((pos) = static_cast<decltype(pos)>((array)->data); \
41  reinterpret_cast<const char*>(pos) < (reinterpret_cast<const char*>((array)->data) + (array)->size); \
42  (pos)++)
43 
44 namespace wayland
45 {
46  class proxy_t;
47 
48  class array_t;
49 
50  namespace detail
51  {
60  int check_return_value(int return_value, std::string const &function_name);
61 
67  template<typename native_t>
69  {
70  private:
71  native_t *object = nullptr;
72 
73  protected:
74  basic_wrapper(native_t *object)
75  : object{object}
76  {
77  }
78 
79  public:
80  basic_wrapper() = default;
81  ~basic_wrapper() noexcept = default;
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> object)
154  : object{std::move(object)}
155  {
156  }
157 
158  std::shared_ptr<native_t> ref_ptr() const
159  {
160  return object;
161  }
162 
163  public:
164  refcounted_wrapper() = default;
165  ~refcounted_wrapper() noexcept = default;
166 
168  {
169  *this = other;
170  }
171 
172  refcounted_wrapper(refcounted_wrapper &&other) noexcept
173  {
174  *this = std::move(other);
175  }
176 
177  native_t *c_ptr() const
178  {
179  if(!object)
180  throw std::runtime_error("Tried to access empty object");
181  return object.get();
182  }
183 
184  bool has_object() const
185  {
186  return !!object;
187  }
188 
189  operator bool() const
190  {
191  return has_object();
192  }
193 
194  operator native_t*() const
195  {
196  return c_ptr();
197  }
198 
199  refcounted_wrapper& operator=(const refcounted_wrapper &right)
200  {
201  // Check for self-assignment
202  if(this == &right)
203  return *this;
204  object = right.object;
205  return *this;
206  }
207 
208  refcounted_wrapper& operator=(refcounted_wrapper &&right) noexcept
209  {
210  std::swap(object, right.object);
211  return *this;
212  }
213 
214  bool operator==(const refcounted_wrapper &right) const
215  {
216  return object == right.object;
217  }
218 
219  bool operator!=(const refcounted_wrapper &right) const
220  {
221  return !(*this == right); // Reuse equals operator
222  }
223  };
224 
225  class any
226  {
227  private:
228  class base
229  {
230  public:
231  base() = default;
232  base(const base&) = default;
233  base(base&&) noexcept = default;
234  base& operator=(const base&) = default;
235  base& operator=(base&&) noexcept = default;
236  virtual ~base() noexcept = default;
237  virtual const std::type_info &type_info() const = 0;
238  virtual base *clone() const = 0;
239  };
240 
241  template <typename T>
242  class derived : public base
243  {
244  private:
245  T val;
246  friend class any;
247 
248  public:
249  derived(T t)
250  : val(std::move(t)) { }
251 
252  const std::type_info &type_info() const override
253  {
254  return typeid(T);
255  }
256 
257  base *clone() const override
258  {
259  return new derived<T>(val);
260  }
261  };
262 
263  base *val = nullptr;
264 
265  public:
266  any() = default;
267 
268  any(const any &a)
269  : val(a.val ? a.val->clone() : nullptr) { }
270 
271  any(any &&a) noexcept
272  {
273  operator=(std::move(a));
274  }
275 
276  template <typename T>
277  any(const T &t)
278  : val(new derived<T>(t)) { }
279 
280  ~any() noexcept
281  {
282  delete val;
283  }
284 
285  any &operator=(const any &a)
286  {
287  if (&a != this)
288  {
289  delete val;
290  val = a.val ? a.val->clone() : nullptr;
291  }
292  return *this;
293  }
294 
295  any &operator=(any &&a) noexcept
296  {
297  std::swap(val, a.val);
298  return *this;
299  }
300 
301  template <typename T>
302  any &operator=(const T &t)
303  {
304  if(val && typeid(T) == val->type_info())
305  static_cast<derived<T>*>(val)->val = t;
306  else
307  {
308  delete val;
309  val = new derived<T>(t);
310  }
311  return *this;
312  }
313 
314  template <typename T>
315  T &get()
316  {
317  if(val && typeid(T) == val->type_info())
318  return static_cast<derived<T>*>(val)->val;
319  throw std::bad_cast();
320  }
321 
322  template <typename T>
323  const T &get() const
324  {
325  if(val && typeid(T) == val->type_info())
326  return static_cast<derived<T>*>(val)->val;
327  throw std::bad_cast();
328  }
329  };
330 
331  template<unsigned int size, int id = 0>
332  class bitfield
333  {
334  uint32_t v = 0;
335  static const uint32_t mask = (1 << size) - 1;
336 
337  public:
338  explicit bitfield(const uint32_t value = 0)
339  : v(value)
340  {
341  }
342 
343  explicit operator uint32_t() const
344  {
345  return v;
346  }
347 
348  operator bool() const
349  {
350  return v;
351  }
352 
353  bitfield(const bitfield<size, id> &b)
354  {
355  operator=(b);
356  }
357 
358  bitfield(bitfield<size, id>&&) noexcept = default;
359 
360  ~bitfield() noexcept = default;
361 
362  bool operator==(const bitfield<size, id> &b)
363  {
364  return v == b.v;
365  }
366 
367  bool operator!=(const bitfield<size, id> &b)
368  {
369  return !operator==(b);
370  }
371 
372  bitfield<size, id> &operator=(const bitfield<size, id> &b)
373  {
374  // Check for self-assignment
375  if(this != &b)
376  v = static_cast<uint32_t>(b);
377  return *this;
378  }
379 
380  bitfield<size, id> &operator=(bitfield<size, id> &&) noexcept = default;
381 
382  bitfield<size, id> operator|(const bitfield<size, id> &b) const
383  {
384  return bitfield<size, id>(v | static_cast<uint32_t>(b));
385  }
386 
387  bitfield<size, id> operator&(const bitfield<size, id> &b) const
388  {
389  return bitfield<size, id>(v & static_cast<uint32_t>(b));
390  }
391 
392  bitfield<size, id> operator^(const bitfield<size, id> &b) const
393  {
394  return bitfield<size, id>((v ^ static_cast<uint32_t>(b)) & mask);
395  }
396 
397  bitfield<size, id> operator~() const
398  {
399  return bitfield<size, id>(~v & mask);
400  }
401 
402  bitfield<size, id> &operator|=(const bitfield<size, id> &b)
403  {
404  operator=(*this | b);
405  return *this;
406  }
407 
408  bitfield<size, id> &operator&=(const bitfield<size, id> &b)
409  {
410  operator=(*this & b);
411  return *this;
412  }
413 
414  bitfield<size, id> &operator^=(const bitfield<size, id> &b)
415  {
416  operator=(*this ^ b);
417  return *this;
418  }
419  };
420 
421  class argument_t
422  {
423  private:
424  wl_argument argument = { .i = 0 };
425  bool is_array{false};
426 
427  // Uninitialized argument - only for internal use
428  argument_t() = default;
429  public:
430 
431  argument_t(const argument_t &arg);
432  argument_t(argument_t &&) noexcept = default;
433  argument_t &operator=(const argument_t &arg);
434  argument_t &operator=(argument_t&&) noexcept = default;
435  ~argument_t() noexcept;
436 
437  // handles integers
438  argument_t(uint32_t i);
439  argument_t(int32_t i);
440 
441  // handles wl_fixed_t
442  argument_t(double f);
443 
444  // handles strings
445  argument_t(const std::string &s);
446 
447  // handles objects
448  argument_t(wl_object *o);
449 
450  // handles arrays
451  argument_t(const array_t& a);
452 
453  // handles null objects, for example for new-id arguments
454  argument_t(std::nullptr_t);
455 
456  // handles file descriptors (have same type as signed integers, so extra function)
457  static argument_t fd(int fileno);
458 
462  wl_argument get_c_argument() const;
463  };
464  }
465 
466  class array_t
467  {
468  private:
469  wl_array a = { 0, 0, nullptr };
470 
471  array_t(wl_array *arr);
472  void get(wl_array *arr) const;
473 
474  friend class proxy_t;
475  friend class detail::argument_t;
476 
477  public:
478  array_t();
479  array_t(const array_t &arr);
480  array_t(array_t &&arr) noexcept;
481 
482  template <typename T> array_t(const std::vector<T> &v)
483  {
484  wl_array_init(&a);
485  wl_array_add(&a, v.size()*sizeof(T));
486  T *p = nullptr;
487  unsigned int c = 0;
488  wl_array_for_each_cpp(p, &a)
489  *p = v.at(c++);
490  }
491 
492  ~array_t();
493  array_t &operator=(const array_t &arr);
494  array_t &operator=(array_t &&arr) noexcept;
495 
496  template <typename T> array_t &operator=(const std::vector<T> &v)
497  {
498  wl_array_release(&a);
499  wl_array_init(&a);
500  wl_array_add(&a, v.size()*sizeof(T));
501  T *p = nullptr;
502  unsigned int c = 0;
503  wl_array_for_each_cpp(p, &a)
504  *p = v.at(c++);
505  return *this;
506  }
507 
508  template <typename T> operator std::vector<T>() const
509  {
510  std::vector<T> v;
511  T *p = nullptr;
512  wl_array_for_each_cpp(p, &a)
513  v.push_back(*p);
514  return v;
515  }
516  };
517 }
518 
519 #endif
STL namespace.
Refcounted wrapper for C objects.
Non-refcounted wrapper for C objects.