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 #include <wayland-util.hpp>
27 
28 #include <cerrno>
29 #include <limits>
30 #include <system_error>
31 
32 using namespace wayland;
33 using namespace wayland::detail;
34 
35 namespace wayland
36 {
37   namespace detail
38   {
check_return_value(int return_value,const std::string & function_name)39     int check_return_value(int return_value, const std::string &function_name)
40     {
41       if(return_value < 0)
42         throw std::system_error(errno, std::generic_category(), function_name);
43       return return_value;
44     }
45   }
46 }
47 
argument_t(const argument_t & arg)48 argument_t::argument_t(const argument_t &arg)
49 {
50   operator=(arg);
51 }
52 
operator =(const argument_t & arg)53 argument_t &argument_t::operator=(const argument_t &arg)
54 {
55   // Check for self-assignment
56   if(this == &arg)
57     return *this;
58 
59   if(is_array)
60     {
61       wl_array_release(argument.a);
62       delete argument.a;
63     }
64 
65   is_array = arg.is_array;
66 
67   if(arg.is_array)
68     {
69       argument.a = new wl_array;
70       wl_array_init(argument.a);
71       if(wl_array_copy(argument.a, arg.argument.a) < 0)
72         throw std::runtime_error("wl_array_copy failed.");
73     }
74   else
75     argument = arg.argument;
76 
77   return *this;
78 }
79 
~argument_t()80 argument_t::~argument_t() noexcept
81 {
82   if(is_array)
83     {
84       wl_array_release(argument.a);
85       delete argument.a;
86     }
87 }
88 
argument_t(uint32_t i)89 argument_t::argument_t(uint32_t i)
90 {
91   argument.u = i;
92 }
93 
argument_t(int32_t i)94 argument_t::argument_t(int32_t i)
95 {
96   argument.i = i;
97 }
98 
argument_t(double f)99 argument_t::argument_t(double f)
100 {
101   argument.f = wl_fixed_from_double(f);
102 }
103 
argument_t(const std::string & s)104 argument_t::argument_t(const std::string &s)
105 {
106   argument.s = s.c_str();
107 }
108 
argument_t(wl_object * o)109 argument_t::argument_t(wl_object *o)
110 {
111   argument.o = o;
112   is_array = false;
113 }
114 
argument_t(std::nullptr_t)115 argument_t::argument_t(std::nullptr_t)
116 {
117   argument.n = 0;
118 }
119 
argument_t(const array_t & a)120 argument_t::argument_t(const array_t& a)
121 {
122   argument.a = new wl_array;
123   a.get(argument.a);
124   is_array = true;
125 }
126 
fd(int fileno)127 argument_t argument_t::fd(int fileno)
128 {
129   if(fileno > std::numeric_limits<int32_t>::max())
130     throw std::invalid_argument("FD number too big");
131   argument_t arg;
132   arg.argument.h = static_cast<int32_t> (fileno);
133   return arg;
134 }
135 
get_c_argument() const136 wl_argument argument_t::get_c_argument() const
137 {
138   return argument;
139 }
140 
array_t(wl_array * arr)141 array_t::array_t(wl_array *arr)
142 {
143   wl_array_init(&a);
144   wl_array_copy(&a, arr);
145 }
146 
get(wl_array * arr) const147 void array_t::get(wl_array *arr) const
148 {
149   wl_array_init(arr);
150   wl_array_copy(arr, const_cast<wl_array*>(&a));
151 }
152 
array_t()153 array_t::array_t()
154 {
155   wl_array_init(&a);
156 }
157 
array_t(const array_t & arr)158 array_t::array_t(const array_t &arr)
159 {
160   wl_array_init(&a);
161   wl_array_copy(&a, const_cast<wl_array*>(&arr.a));
162 }
163 
array_t(array_t && arr)164 array_t::array_t(array_t &&arr) noexcept
165 {
166   wl_array_init(&a);
167   std::swap(a, arr.a);
168 }
169 
~array_t()170 array_t::~array_t()
171 {
172   wl_array_release(&a);
173 }
174 
operator =(const array_t & arr)175 array_t &array_t::operator=(const array_t &arr)
176 {
177   // Check for self-assignment
178   if(this == &arr)
179     return *this;
180 
181   wl_array_release(&a);
182   wl_array_init(&a);
183   wl_array_copy(&a, const_cast<wl_array*>(&arr.a));
184   return *this;
185 }
186 
operator =(array_t && arr)187 array_t &array_t::operator=(array_t &&arr) noexcept
188 {
189   std::swap(a, arr.a);
190   return *this;
191 }
192