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 #include <stdexcept>
37 
38 #include <wayland-client-core.h>
39 
40 #define wl_array_for_each_cpp(pos, array) \
41  for ((pos) = static_cast<decltype(pos)>((array)->data); \
42  reinterpret_cast<const char*>(pos) < (reinterpret_cast<const char*>((array)->data) + (array)->size); \
43  (pos)++)
44 
45 namespace wayland
46 {
47  class proxy_t;
48 
49  class array_t;
50 
51  namespace detail
52  {
61  int check_return_value(int return_value, std::string const &function_name);
62 
68  template<typename native_t>
70  {
71  private:
72  native_t *object = nullptr;
73 
74  protected:
75  basic_wrapper(native_t *object)
76  : object{object}
77  {
78  }
79 
80  public:
81  basic_wrapper() = default;
82  ~basic_wrapper() noexcept = default;
83 
84  basic_wrapper(basic_wrapper const &other)
85  {
86  *this = other;
87  }
88 
89  basic_wrapper(basic_wrapper &&other) noexcept
90  {
91  *this = std::move(other);
92  }
93 
94  native_t *c_ptr() const
95  {
96  if(!object)
97  throw std::runtime_error("Tried to access empty object");
98  return object;
99  }
100 
101  bool has_object() const
102  {
103  return object;
104  }
105 
106  operator bool() const
107  {
108  return has_object();
109  }
110 
111  operator native_t*() const
112  {
113  return c_ptr();
114  }
115 
116  basic_wrapper& operator=(const basic_wrapper &right)
117  {
118  // Check for self-assignment
119  if(this == &right)
120  return *this;
121  object = right.object;
122  return *this;
123  }
124 
125  basic_wrapper& operator=(basic_wrapper &&right) noexcept
126  {
127  std::swap(object, right.object);
128  return *this;
129  }
130 
131  bool operator==(const basic_wrapper &right) const
132  {
133  return object == right.object;
134  }
135 
136  bool operator!=(const basic_wrapper &right) const
137  {
138  return !(*this == right); // Reuse equals operator
139  }
140  };
141 
147  template<typename native_t>
149  {
150  private:
151  std::shared_ptr<native_t> object;
152 
153  protected:
154  refcounted_wrapper(std::shared_ptr<native_t> object)
155  : object{std::move(object)}
156  {
157  }
158 
159  std::shared_ptr<native_t> ref_ptr() const
160  {
161  return object;
162  }
163 
164  public:
165  refcounted_wrapper() = default;
166  ~refcounted_wrapper() noexcept = default;
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  base() = default;
233  base(const base&) = default;
234  base(base&&) noexcept = default;
235  base& operator=(const base&) = default;
236  base& operator=(base&&) noexcept = default;
237  virtual ~base() noexcept = default;
238  virtual const std::type_info &type_info() const = 0;
239  virtual base *clone() const = 0;
240  };
241 
242  template <typename T>
243  class derived : public base
244  {
245  private:
246  T val;
247  friend class any;
248 
249  public:
250  derived(T t)
251  : val(std::move(t)) { }
252 
253  const std::type_info &type_info() const override
254  {
255  return typeid(T);
256  }
257 
258  base *clone() const override
259  {
260  return new derived<T>(val);
261  }
262  };
263 
264  base *val = nullptr;
265 
266  public:
267  any() = default;
268 
269  any(const any &a)
270  : val(a.val ? a.val->clone() : nullptr) { }
271 
272  any(any &&a) noexcept
273  {
274  operator=(std::move(a));
275  }
276 
277  template <typename T>
278  any(const T &t)
279  : val(new derived<T>(t)) { }
280 
281  ~any() noexcept
282  {
283  delete val;
284  }
285 
286  any &operator=(const any &a)
287  {
288  if (&a != this)
289  {
290  delete val;
291  val = a.val ? a.val->clone() : nullptr;
292  }
293  return *this;
294  }
295 
296  any &operator=(any &&a) noexcept
297  {
298  std::swap(val, a.val);
299  return *this;
300  }
301 
302  template <typename T>
303  any &operator=(const T &t)
304  {
305  if(val && typeid(T) == val->type_info())
306  static_cast<derived<T>*>(val)->val = t;
307  else
308  {
309  delete val;
310  val = new derived<T>(t);
311  }
312  return *this;
313  }
314 
315  template <typename T>
316  T &get()
317  {
318  if(val && typeid(T) == val->type_info())
319  return static_cast<derived<T>*>(val)->val;
320  throw std::bad_cast();
321  }
322 
323  template <typename T>
324  const T &get() const
325  {
326  if(val && typeid(T) == val->type_info())
327  return static_cast<derived<T>*>(val)->val;
328  throw std::bad_cast();
329  }
330  };
331 
332  template<unsigned int size, int id = 0>
333  class bitfield
334  {
335  uint32_t v = 0;
336  static const uint32_t mask = (1 << size) - 1;
337 
338  public:
339  explicit bitfield(const uint32_t value = 0)
340  : v(value)
341  {
342  }
343 
344  explicit operator uint32_t() const
345  {
346  return v;
347  }
348 
349  operator bool() const
350  {
351  return v;
352  }
353 
354  bitfield(const bitfield<size, id> &b)
355  {
356  operator=(b);
357  }
358 
359  bitfield(bitfield<size, id>&&) noexcept = default;
360 
361  ~bitfield() noexcept = default;
362 
363  bool operator==(const bitfield<size, id> &b)
364  {
365  return v == b.v;
366  }
367 
368  bool operator!=(const bitfield<size, id> &b)
369  {
370  return !operator==(b);
371  }
372 
373  bitfield<size, id> &operator=(const bitfield<size, id> &b)
374  {
375  // Check for self-assignment
376  if(this != &b)
377  v = static_cast<uint32_t>(b);
378  return *this;
379  }
380 
381  bitfield<size, id> &operator=(bitfield<size, id> &&) noexcept = default;
382 
383  bitfield<size, id> operator|(const bitfield<size, id> &b) const
384  {
385  return bitfield<size, id>(v | static_cast<uint32_t>(b));
386  }
387 
388  bitfield<size, id> operator&(const bitfield<size, id> &b) const
389  {
390  return bitfield<size, id>(v & static_cast<uint32_t>(b));
391  }
392 
393  bitfield<size, id> operator^(const bitfield<size, id> &b) const
394  {
395  return bitfield<size, id>((v ^ static_cast<uint32_t>(b)) & mask);
396  }
397 
398  bitfield<size, id> operator~() const
399  {
400  return bitfield<size, id>(~v & mask);
401  }
402 
403  bitfield<size, id> &operator|=(const bitfield<size, id> &b)
404  {
405  operator=(*this | b);
406  return *this;
407  }
408 
409  bitfield<size, id> &operator&=(const bitfield<size, id> &b)
410  {
411  operator=(*this & b);
412  return *this;
413  }
414 
415  bitfield<size, id> &operator^=(const bitfield<size, id> &b)
416  {
417  operator=(*this ^ b);
418  return *this;
419  }
420  };
421 
422  class argument_t
423  {
424  private:
425  wl_argument argument = { .i = 0 };
426  bool is_array{false};
427 
428  // Uninitialized argument - only for internal use
429  argument_t() = default;
430  public:
431 
432  argument_t(const argument_t &arg);
433  argument_t(argument_t &&) noexcept = default;
434  argument_t &operator=(const argument_t &arg);
435  argument_t &operator=(argument_t&&) noexcept = default;
436  ~argument_t() noexcept;
437 
438  // handles integers
439  argument_t(uint32_t i);
440  argument_t(int32_t i);
441 
442  // handles wl_fixed_t
443  argument_t(double f);
444 
445  // handles strings
446  argument_t(const std::string &s);
447 
448  // handles objects
449  argument_t(wl_object *o);
450 
451  // handles arrays
452  argument_t(const array_t& a);
453 
454  // handles null objects, for example for new-id arguments
455  argument_t(std::nullptr_t);
456 
457  // handles file descriptors (have same type as signed integers, so extra function)
458  static argument_t fd(int fileno);
459 
463  wl_argument get_c_argument() const;
464  };
465  }
466 
467  class array_t
468  {
469  private:
470  wl_array a = { 0, 0, nullptr };
471 
472  array_t(wl_array *arr);
473  void get(wl_array *arr) const;
474 
475  friend class proxy_t;
476  friend class detail::argument_t;
477 
478  public:
479  array_t();
480  array_t(const array_t &arr);
481  array_t(array_t &&arr) noexcept;
482 
483  template <typename T> array_t(const std::vector<T> &v)
484  {
485  wl_array_init(&a);
486  wl_array_add(&a, v.size()*sizeof(T));
487  T *p = nullptr;
488  unsigned int c = 0;
489  wl_array_for_each_cpp(p, &a)
490  *p = v.at(c++);
491  }
492 
493  ~array_t();
494  array_t &operator=(const array_t &arr);
495  array_t &operator=(array_t &&arr) noexcept;
496 
497  template <typename T> array_t &operator=(const std::vector<T> &v)
498  {
499  wl_array_release(&a);
500  wl_array_init(&a);
501  wl_array_add(&a, v.size()*sizeof(T));
502  T *p = nullptr;
503  unsigned int c = 0;
504  wl_array_for_each_cpp(p, &a)
505  *p = v.at(c++);
506  return *this;
507  }
508 
509  template <typename T> operator std::vector<T>() const
510  {
511  std::vector<T> v;
512  T *p = nullptr;
513  wl_array_for_each_cpp(p, &a)
514  v.push_back(*p);
515  return v;
516  }
517  };
518 }
519 
520 #endif
Non-refcounted wrapper for C objects.
Refcounted wrapper for C objects.