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 { 52 /** \brief Check the return value of a C function and throw exception on 53 * failure 54 * 55 * \param return_value return value of the function to check 56 * \param function_name name of the function, for error message 57 * \return return_value if it was >= 0 58 * \exception std::system_error with errno if return_value < 0 59 */ 60 int check_return_value(int return_value, std::string const &function_name); 61 62 /** \brief Non-refcounted wrapper for C objects 63 * 64 * This is by default copyable. If this is not desired, delete the 65 * copy constructor and copy assignment operator in derived classes. 66 */ 67 template<typename native_t> 68 class basic_wrapper 69 { 70 private: 71 native_t *object = nullptr; 72 73 protected: basic_wrapper(native_t * object)74 basic_wrapper(native_t *object) 75 : object{object} 76 { 77 } 78 79 public: 80 basic_wrapper() = default; 81 ~basic_wrapper() noexcept = default; 82 basic_wrapper(basic_wrapper const & other)83 basic_wrapper(basic_wrapper const &other) 84 { 85 *this = other; 86 } 87 basic_wrapper(basic_wrapper && other)88 basic_wrapper(basic_wrapper &&other) noexcept 89 { 90 *this = std::move(other); 91 } 92 c_ptr() const93 native_t *c_ptr() const 94 { 95 if(!object) 96 throw std::runtime_error("Tried to access empty object"); 97 return object; 98 } 99 has_object() const100 bool has_object() const 101 { 102 return object; 103 } 104 operator bool() const105 operator bool() const 106 { 107 return has_object(); 108 } 109 operator native_t*() const110 operator native_t*() const 111 { 112 return c_ptr(); 113 } 114 operator =(const basic_wrapper & right)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 operator =(basic_wrapper && right)124 basic_wrapper& operator=(basic_wrapper &&right) noexcept 125 { 126 std::swap(object, right.object); 127 return *this; 128 } 129 operator ==(const basic_wrapper & right) const130 bool operator==(const basic_wrapper &right) const 131 { 132 return object == right.object; 133 } 134 operator !=(const basic_wrapper & right) const135 bool operator!=(const basic_wrapper &right) const 136 { 137 return !(*this == right); // Reuse equals operator 138 } 139 }; 140 141 /** \brief Refcounted wrapper for C objects 142 * 143 * This is by default copyable. If this is not desired, delete the 144 * copy constructor and copy assignment operator in derived classes. 145 */ 146 template<typename native_t> 147 class refcounted_wrapper 148 { 149 private: 150 std::shared_ptr<native_t> object; 151 152 protected: refcounted_wrapper(std::shared_ptr<native_t> object)153 refcounted_wrapper(std::shared_ptr<native_t> object) 154 : object{std::move(object)} 155 { 156 } 157 ref_ptr() const158 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 refcounted_wrapper(refcounted_wrapper const & other)167 refcounted_wrapper(refcounted_wrapper const &other) 168 { 169 *this = other; 170 } 171 refcounted_wrapper(refcounted_wrapper && other)172 refcounted_wrapper(refcounted_wrapper &&other) noexcept 173 { 174 *this = std::move(other); 175 } 176 c_ptr() const177 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 has_object() const184 bool has_object() const 185 { 186 return !!object; 187 } 188 operator bool() const189 operator bool() const 190 { 191 return has_object(); 192 } 193 operator native_t*() const194 operator native_t*() const 195 { 196 return c_ptr(); 197 } 198 operator =(const refcounted_wrapper & right)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 operator =(refcounted_wrapper && right)208 refcounted_wrapper& operator=(refcounted_wrapper &&right) noexcept 209 { 210 std::swap(object, right.object); 211 return *this; 212 } 213 operator ==(const refcounted_wrapper & right) const214 bool operator==(const refcounted_wrapper &right) const 215 { 216 return object == right.object; 217 } 218 operator !=(const refcounted_wrapper & right) const219 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: derived(T t)249 derived(T t) 250 : val(std::move(t)) { } 251 type_info() const252 const std::type_info &type_info() const override 253 { 254 return typeid(T); 255 } 256 clone() const257 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 any(const any & a)268 any(const any &a) 269 : val(a.val ? a.val->clone() : nullptr) { } 270 any(any && a)271 any(any &&a) noexcept 272 { 273 operator=(std::move(a)); 274 } 275 276 template <typename T> any(const T & t)277 any(const T &t) 278 : val(new derived<T>(t)) { } 279 ~any()280 ~any() noexcept 281 { 282 delete val; 283 } 284 operator =(const any & a)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 operator =(any && a)295 any &operator=(any &&a) noexcept 296 { 297 std::swap(val, a.val); 298 return *this; 299 } 300 301 template <typename T> operator =(const T & 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> get()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> get() const323 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: bitfield(const uint32_t value=0)338 explicit bitfield(const uint32_t value = 0) 339 : v(value) 340 { 341 } 342 operator uint32_t() const343 explicit operator uint32_t() const 344 { 345 return v; 346 } 347 operator bool() const348 operator bool() const 349 { 350 return v; 351 } 352 bitfield(const bitfield<size,id> & b)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 operator ==(const bitfield<size,id> & b)362 bool operator==(const bitfield<size, id> &b) 363 { 364 return v == b.v; 365 } 366 operator !=(const bitfield<size,id> & b)367 bool operator!=(const bitfield<size, id> &b) 368 { 369 return !operator==(b); 370 } 371 operator =(const bitfield<size,id> & b)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 operator |(const bitfield<size,id> & b) const382 bitfield<size, id> operator|(const bitfield<size, id> &b) const 383 { 384 return bitfield<size, id>(v | static_cast<uint32_t>(b)); 385 } 386 operator &(const bitfield<size,id> & b) const387 bitfield<size, id> operator&(const bitfield<size, id> &b) const 388 { 389 return bitfield<size, id>(v & static_cast<uint32_t>(b)); 390 } 391 operator ^(const bitfield<size,id> & b) const392 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 operator ~() const397 bitfield<size, id> operator~() const 398 { 399 return bitfield<size, id>(~v & mask); 400 } 401 operator |=(const bitfield<size,id> & b)402 bitfield<size, id> &operator|=(const bitfield<size, id> &b) 403 { 404 operator=(*this | b); 405 return *this; 406 } 407 operator &=(const bitfield<size,id> & b)408 bitfield<size, id> &operator&=(const bitfield<size, id> &b) 409 { 410 operator=(*this & b); 411 return *this; 412 } 413 operator ^=(const bitfield<size,id> & b)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 459 /** 460 * Get the contained wl_argument. 461 */ 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 array_t(const std::vector<T> & v)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 operator =(const std::vector<T> & v)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 operator std::vector<T>() const508 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 520