Wayland++  0.2.3
C++ Bindings for Wayland
wayland-util.hpp
1 
2 /*
3  * Copyright (c) 2014-2017, Nils Christopher Brause
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #ifndef WAYLAND_UTIL_HPP
28 #define WAYLAND_UTIL_HPP
29 
30 #include <algorithm>
31 #include <memory>
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 = (decltype(pos))(array)->data; \
41  (const char *) pos < ((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  virtual const std::type_info &type_info() const override
250  {
251  return typeid(T);
252  }
253 
254  virtual 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  else
304  throw std::bad_cast();
305  }
306  };
307 
308  template<unsigned int size, int id = 0>
309  class bitfield
310  {
311  uint32_t v;
312  static const uint32_t mask = (1 << size) - 1;
313 
314  public:
315  explicit bitfield(const uint32_t value = 0)
316  : v(value)
317  {
318  }
319 
320  explicit operator uint32_t() const
321  {
322  return v;
323  }
324 
325  operator bool() const
326  {
327  return v;
328  }
329 
330  bitfield(const bitfield<size, id> &b)
331  {
332  operator=(b);
333  }
334 
335  bool operator==(const bitfield<size, id> &b)
336  {
337  return v == b.v;
338  }
339 
340  bool operator!=(const bitfield<size, id> &b)
341  {
342  return !operator==(b);
343  }
344 
345  bitfield<size, id> &operator=(const bitfield<size, id> &b)
346  {
347  v = static_cast<uint32_t>(b);
348  return *this;
349  }
350 
351  bitfield<size, id> operator|(const bitfield<size, id> &b) const
352  {
353  return bitfield<size, id>(v | static_cast<uint32_t>(b));
354  }
355 
356  bitfield<size, id> operator&(const bitfield<size, id> &b) const
357  {
358  return bitfield<size, id>(v & static_cast<uint32_t>(b));
359  }
360 
361  bitfield<size, id> operator^(const bitfield<size, id> &b) const
362  {
363  return bitfield<size, id>((v ^ static_cast<uint32_t>(b)) & mask);
364  }
365 
366  bitfield<size, id> operator~() const
367  {
368  return bitfield<size, id>(~v & mask);
369  }
370 
371  bitfield<size, id> &operator|=(const bitfield<size, id> &b)
372  {
373  operator=(*this | b);
374  return *this;
375  }
376 
377  bitfield<size, id> &operator&=(const bitfield<size, id> &b)
378  {
379  operator=(*this & b);
380  return *this;
381  }
382 
383  bitfield<size, id> &operator^=(const bitfield<size, id> &b)
384  {
385  operator=(*this ^ b);
386  return *this;
387  }
388  };
389 
390  class argument_t
391  {
392  private:
393  bool is_array{false};
394  // Uninitialized argument - only for internal use
395  argument_t();
396 
397  public:
398  wl_argument argument;
399 
400  argument_t(const argument_t &arg);
401  argument_t &operator=(const argument_t &arg);
402  ~argument_t();
403 
404  // handles integers
405  argument_t(uint32_t i);
406  argument_t(int32_t i);
407 
408  // handles wl_fixed_t
409  argument_t(double f);
410 
411  // handles strings
412  argument_t(const std::string &s);
413 
414  // handles objects
415  argument_t(wl_object *o);
416 
417  // handles arrays
418  argument_t(array_t a);
419 
420  // handles null objects, for example for new-id arguments
421  argument_t(std::nullptr_t);
422 
423  // handles file descriptors (have same type as signed integers, so extra function)
424  static argument_t fd(int fileno);
425  };
426  }
427 
428  class array_t
429  {
430  private:
431  wl_array a;
432 
433  array_t(wl_array *arr);
434  void get(wl_array *arr) const;
435 
436  friend class proxy_t;
437  friend class detail::argument_t;
438 
439  public:
440  array_t();
441  array_t(const array_t &arr);
442  array_t(array_t &&arr);
443 
444  template <typename T> array_t(const std::vector<T> &v)
445  {
446  wl_array_init(&a);
447  wl_array_add(&a, v.size()*sizeof(T));
448  T *p;
449  unsigned int c = 0;
450  wl_array_for_each_cpp(p, &a)
451  *p = v.at(c++);
452  }
453 
454  ~array_t();
455  array_t &operator=(const array_t &arr);
456  array_t &operator=(array_t &&arr);
457 
458  template <typename T> array_t &operator=(const std::vector<T> &v)
459  {
460  wl_array_release(&a);
461  wl_array_init(&a);
462  wl_array_add(&a, v.size()*sizeof(T));
463  T *p;
464  unsigned int c = 0;
465  wl_array_for_each_cpp(p, &a)
466  *p = v.at(c++);
467  return *this;
468  }
469 
470  template <typename T> operator std::vector<T>() const
471  {
472  std::vector<T> v;
473  T *p;
474  wl_array_for_each_cpp(p, &a)
475  v.push_back(*p);
476  return v;
477  }
478  };
479 }
480 
481 #endif
Refcounted wrapper for C objects.
Non-refcounted wrapper for C objects.