Wayland++  0.2.5
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 = (decltype(pos))(array)->data; \
40  (const char *) pos < ((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  virtual const std::type_info &type_info() const override
249  {
250  return typeid(T);
251  }
252 
253  virtual 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  else
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
Refcounted wrapper for C objects.
Non-refcounted wrapper for C objects.