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