1/**************************************************************************/
2/* callable_bind.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "callable_bind.h"
32
33//////////////////////////////////
34
35uint32_t CallableCustomBind::hash() const {
36 return callable.hash();
37}
38String CallableCustomBind::get_as_text() const {
39 return callable.operator String();
40}
41
42bool CallableCustomBind::_equal_func(const CallableCustom *p_a, const CallableCustom *p_b) {
43 const CallableCustomBind *a = static_cast<const CallableCustomBind *>(p_a);
44 const CallableCustomBind *b = static_cast<const CallableCustomBind *>(p_b);
45
46 if (!(a->callable != b->callable)) {
47 return false;
48 }
49
50 if (a->binds.size() != b->binds.size()) {
51 return false;
52 }
53
54 return true;
55}
56
57bool CallableCustomBind::_less_func(const CallableCustom *p_a, const CallableCustom *p_b) {
58 const CallableCustomBind *a = static_cast<const CallableCustomBind *>(p_a);
59 const CallableCustomBind *b = static_cast<const CallableCustomBind *>(p_b);
60
61 if (a->callable < b->callable) {
62 return true;
63 } else if (b->callable < a->callable) {
64 return false;
65 }
66
67 return a->binds.size() < b->binds.size();
68}
69
70CallableCustom::CompareEqualFunc CallableCustomBind::get_compare_equal_func() const {
71 return _equal_func;
72}
73
74CallableCustom::CompareLessFunc CallableCustomBind::get_compare_less_func() const {
75 return _less_func;
76}
77
78bool CallableCustomBind::is_valid() const {
79 return callable.is_valid();
80}
81
82StringName CallableCustomBind::get_method() const {
83 return callable.get_method();
84}
85
86ObjectID CallableCustomBind::get_object() const {
87 return callable.get_object_id();
88}
89
90const Callable *CallableCustomBind::get_base_comparator() const {
91 return callable.get_base_comparator();
92}
93
94int CallableCustomBind::get_bound_arguments_count() const {
95 return callable.get_bound_arguments_count() + binds.size();
96}
97
98void CallableCustomBind::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const {
99 Vector<Variant> sub_args;
100 int sub_count;
101 callable.get_bound_arguments_ref(sub_args, sub_count);
102
103 if (sub_count == 0) {
104 r_arguments = binds;
105 r_argcount = binds.size();
106 return;
107 }
108
109 int new_count = sub_count + binds.size();
110 r_argcount = new_count;
111
112 if (new_count <= 0) {
113 // Removed more arguments than it adds.
114 r_arguments = Vector<Variant>();
115 return;
116 }
117
118 r_arguments.resize(new_count);
119
120 if (sub_count > 0) {
121 for (int i = 0; i < sub_count; i++) {
122 r_arguments.write[i] = sub_args[i];
123 }
124 for (int i = 0; i < binds.size(); i++) {
125 r_arguments.write[i + sub_count] = binds[i];
126 }
127 r_argcount = new_count;
128 } else {
129 for (int i = 0; i < binds.size() + sub_count; i++) {
130 r_arguments.write[i] = binds[i - sub_count];
131 }
132 }
133}
134
135void CallableCustomBind::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
136 const Variant **args = (const Variant **)alloca(sizeof(const Variant **) * (binds.size() + p_argcount));
137 for (int i = 0; i < p_argcount; i++) {
138 args[i] = (const Variant *)p_arguments[i];
139 }
140 for (int i = 0; i < binds.size(); i++) {
141 args[i + p_argcount] = (const Variant *)&binds[i];
142 }
143
144 callable.callp(args, p_argcount + binds.size(), r_return_value, r_call_error);
145}
146
147Error CallableCustomBind::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
148 const Variant **args = (const Variant **)alloca(sizeof(const Variant **) * (binds.size() + p_argcount));
149 for (int i = 0; i < p_argcount; i++) {
150 args[i] = (const Variant *)p_arguments[i];
151 }
152 for (int i = 0; i < binds.size(); i++) {
153 args[i + p_argcount] = (const Variant *)&binds[i];
154 }
155
156 return callable.rpcp(p_peer_id, args, p_argcount + binds.size(), r_call_error);
157}
158
159CallableCustomBind::CallableCustomBind(const Callable &p_callable, const Vector<Variant> &p_binds) {
160 callable = p_callable;
161 binds = p_binds;
162}
163
164CallableCustomBind::~CallableCustomBind() {
165}
166
167//////////////////////////////////
168
169uint32_t CallableCustomUnbind::hash() const {
170 return callable.hash();
171}
172String CallableCustomUnbind::get_as_text() const {
173 return callable.operator String();
174}
175
176bool CallableCustomUnbind::_equal_func(const CallableCustom *p_a, const CallableCustom *p_b) {
177 const CallableCustomUnbind *a = static_cast<const CallableCustomUnbind *>(p_a);
178 const CallableCustomUnbind *b = static_cast<const CallableCustomUnbind *>(p_b);
179
180 if (!(a->callable != b->callable)) {
181 return false;
182 }
183
184 if (a->argcount != b->argcount) {
185 return false;
186 }
187
188 return true;
189}
190
191bool CallableCustomUnbind::_less_func(const CallableCustom *p_a, const CallableCustom *p_b) {
192 const CallableCustomUnbind *a = static_cast<const CallableCustomUnbind *>(p_a);
193 const CallableCustomUnbind *b = static_cast<const CallableCustomUnbind *>(p_b);
194
195 if (a->callable < b->callable) {
196 return true;
197 } else if (b->callable < a->callable) {
198 return false;
199 }
200
201 return a->argcount < b->argcount;
202}
203
204CallableCustom::CompareEqualFunc CallableCustomUnbind::get_compare_equal_func() const {
205 return _equal_func;
206}
207
208CallableCustom::CompareLessFunc CallableCustomUnbind::get_compare_less_func() const {
209 return _less_func;
210}
211
212bool CallableCustomUnbind::is_valid() const {
213 return callable.is_valid();
214}
215
216StringName CallableCustomUnbind::get_method() const {
217 return callable.get_method();
218}
219
220ObjectID CallableCustomUnbind::get_object() const {
221 return callable.get_object_id();
222}
223
224const Callable *CallableCustomUnbind::get_base_comparator() const {
225 return callable.get_base_comparator();
226}
227
228int CallableCustomUnbind::get_bound_arguments_count() const {
229 return callable.get_bound_arguments_count() - argcount;
230}
231
232void CallableCustomUnbind::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const {
233 Vector<Variant> sub_args;
234 int sub_count;
235 callable.get_bound_arguments_ref(sub_args, sub_count);
236
237 r_argcount = sub_args.size() - argcount;
238
239 if (argcount >= sub_args.size()) {
240 r_arguments = Vector<Variant>();
241 } else {
242 sub_args.resize(sub_args.size() - argcount);
243 r_arguments = sub_args;
244 }
245}
246
247void CallableCustomUnbind::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
248 if (argcount > p_argcount) {
249 r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
250 r_call_error.argument = 0;
251 r_call_error.expected = argcount;
252 return;
253 }
254 callable.callp(p_arguments, p_argcount - argcount, r_return_value, r_call_error);
255}
256
257Error CallableCustomUnbind::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
258 if (argcount > p_argcount) {
259 r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
260 r_call_error.argument = 0;
261 r_call_error.expected = argcount;
262 return ERR_UNCONFIGURED;
263 }
264 return callable.rpcp(p_peer_id, p_arguments, p_argcount - argcount, r_call_error);
265}
266
267CallableCustomUnbind::CallableCustomUnbind(const Callable &p_callable, int p_argcount) {
268 callable = p_callable;
269 argcount = p_argcount;
270}
271
272CallableCustomUnbind::~CallableCustomUnbind() {
273}
274