libamxd  6.4.1
Data Model Manager
amxd_object_function.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** SPDX-License-Identifier: BSD-2-Clause-Patent
4 **
5 ** SPDX-FileCopyrightText: Copyright (c) 2023 SoftAtHome
6 **
7 ** Redistribution and use in source and binary forms, with or without modification,
8 ** are permitted provided that the following conditions are met:
9 **
10 ** 1. Redistributions of source code must retain the above copyright notice,
11 ** this list of conditions and the following disclaimer.
12 **
13 ** 2. Redistributions in binary form must reproduce the above copyright notice,
14 ** this list of conditions and the following disclaimer in the documentation
15 ** and/or other materials provided with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each copyright holder
18 ** and contributor hereby grants to those receiving rights under this license
19 ** a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
20 ** (except for failure to satisfy the conditions of this license) patent license
21 ** to make, have made, use, offer to sell, sell, import, and otherwise transfer
22 ** this software, where such license applies only to those patent claims, already
23 ** acquired or hereafter acquired, licensable by such copyright holder or contributor
24 ** that are necessarily infringed by:
25 **
26 ** (a) their Contribution(s) (the licensed copyrights of copyright holders and
27 ** non-copyrightable additions of contributors, in source or binary form) alone;
28 ** or
29 **
30 ** (b) combination of their Contribution(s) with the work of authorship to which
31 ** such Contribution(s) was added by such copyright holder or contributor, if,
32 ** at the time the Contribution is added, such addition causes such combination
33 ** to be necessarily infringed. The patent license shall not apply to any other
34 ** combinations which include the Contribution.
35 **
36 ** Except as expressly stated above, no rights or licenses from any copyright
37 ** holder or contributor is granted under this license, whether expressly, by
38 ** implication, estoppel or otherwise.
39 **
40 ** DISCLAIMER
41 **
42 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
46 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
51 ** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 **
53 ****************************************************************************/
54 
55 #ifndef _GNU_SOURCE
56 #define _GNU_SOURCE
57 #endif
58 
59 #include <stdlib.h>
60 #include <string.h>
61 #include <ctype.h>
62 
63 #include "amxd_priv.h"
64 
65 #include <amxd/amxd_common.h>
66 #include <amxd/amxd_object.h>
67 #include <amxd/amxd_action.h>
68 #include <amxd/amxd_function.h>
69 
70 #include "amxd_dm_priv.h"
71 #include "amxd_object_priv.h"
72 #include "amxd_assert.h"
73 
74 static int is_brace(int c) {
75  return ((c == '(') || (c == ')'));
76 }
77 
78 static bool amxd_object_can_invoke_function(const amxd_object_t* const object,
79  const amxd_function_t* const func) {
80  bool retval = false;
81 
83  when_true(func->attr.instance == 0, exit);
84  }
86  when_true(func->attr.templ == 0, exit);
87  }
88 
89  retval = true;
90 
91 exit:
92  return retval;
93 }
94 
96  amxc_var_t* args) {
97  amxc_var_t* call_id = GET_ARG(args, "_call_id");
98  amxc_var_delete(&call_id);
99  amxc_llist_for_each(it, (&func->args)) {
100  amxd_func_arg_t* arg = amxc_llist_it_get_data(it, amxd_func_arg_t, it);
101  amxc_var_t* in_arg = amxc_var_get_key(args,
102  arg->name,
103  AMXC_VAR_FLAG_DEFAULT);
104  if(arg->attr.out == 0) {
105  amxc_var_delete(&in_arg);
106  }
107  }
108 }
109 
111  amxd_function_t** func,
112  const char* func_name,
113  amxc_var_t* const args) {
115 
116  when_null(object, exit);
117  when_str_empty_status(func_name, exit, retval = amxd_status_invalid_name);
118  when_null_status(args, exit, retval = amxd_status_invalid_function_argument);
119  when_true_status(amxc_var_type_of(args) != AMXC_VAR_ID_HTABLE,
120  exit,
122  *func = amxd_object_get_function(object, func_name);
123  when_null_status(*func, exit, retval = amxd_status_function_not_found);
124  when_true_status(!amxd_function_are_args_valid(*func, args),
125  exit,
127  when_true_status(!amxd_object_can_invoke_function(object, *func),
128  exit,
130  when_null_status((*func)->impl,
131  exit,
133 
134  retval = amxd_status_ok;
135 
136 exit:
137  return retval;
138 }
139 
141  amxd_function_t* const func) {
143  amxd_function_t* object_func = NULL;
144  when_null(object, exit);
145  when_null(func, exit);
146  when_not_null(func->it.llist, exit);
147  when_true(amxd_object_is_attr_set(object, amxd_oattr_locked), exit);
148 
149  amxc_llist_for_each(it, (&object->functions)) {
150  const char* object_func_name = NULL;
151  const char* func_name = NULL;
152  object_func = amxc_llist_it_get_data(it, amxd_function_t, it);
153  object_func_name = amxd_function_get_name(object_func);
154  func_name = amxd_function_get_name(func);
155  if(strcmp(func_name, object_func_name) == 0) {
156  break;
157  }
158  object_func = NULL;
159  }
160 
161  if(object_func == NULL) {
162  // functions added to template object by default only work on
163  // instances. This is a design descision.
164  // For other behavior set the attributes before adding the function
165  // to the object
167  if((func->attr.instance == 0) &&
168  ( func->attr.templ == 0)) {
169  func->attr.instance = 1;
170  }
171  }
172  amxc_llist_append(&object->functions, &func->it);
173  retval = amxd_status_ok;
174  } else {
175  retval = amxd_status_duplicate;
176  }
177 
178 exit:
179  return retval;
180 }
181 
183  const char* name,
184  amxd_object_fn_t impl) {
186  amxd_function_t* func = NULL;
187  amxd_object_t* owner = NULL;
188 
189  when_null(object, exit);
190  when_str_empty(name, exit);
191 
192  func = amxd_object_get_function(object, name);
193  when_null(func, exit);
194  owner = amxd_function_get_owner(func);
195  if(owner == object) {
196  func->impl = impl;
197  retval = amxd_status_ok;
198  } else {
199  amxd_function_t* new_func = NULL;
200  retval = amxd_function_copy(&new_func, func);
201  when_true(retval != amxd_status_ok, exit);
202  new_func->impl = impl;
203  when_failed(amxc_llist_append(&object->functions, &new_func->it), exit);
204  }
205 
206 exit:
207  return retval;
208 }
209 
211  const char* name) {
212  amxd_function_t* func = NULL;
213  amxc_string_t normalized;
214 
215  amxc_string_init(&normalized, 0);
216 
217  when_null(object, exit);
218  when_str_empty(name, exit);
219 
220  amxc_string_setf(&normalized, "%s", name);
221  amxc_string_trimr(&normalized, is_brace);
222 
223  func = amxd_object_get_self_func(object, amxc_string_get(&normalized, 0));
224 
225  when_not_null(func, exit);
226 
228  func = amxd_object_get_function(amxd_object_get_parent(object), amxc_string_get(&normalized, 0));
229  } else {
230  if(amxc_llist_it_is_in_list(&object->derived_from)) {
231  amxd_object_t* super = NULL;
232  super = amxc_container_of(object->derived_from.llist,
234  derived_objects);
235  func = amxd_object_get_function(super, amxc_string_get(&normalized, 0));
236  }
237  }
238 
239 exit:
240  amxc_string_clean(&normalized);
241 
242  return func;
243 }
244 
246  const char* func_name,
247  amxc_var_t* const args,
248  amxc_var_t* const ret) {
250  amxd_function_t* func = NULL;
251 
252  when_null(ret, exit);
253  retval = amxd_object_invoke_check(object, &func, func_name, args);
254  when_failed(retval, exit);
255 
256  retval = func->impl(object, func, args, ret);
257  amxd_function_remove_in_args(func, args);
258 
259  if(retval == amxd_status_deferred) {
260  amxd_dm_t* dm = amxd_object_get_dm(object);
261  uint64_t call_id = amxc_var_constcast(uint64_t, ret);
263  if(call_ctx == NULL) {
264  retval = amxd_status_unknown_error;
265  amxc_var_clean(ret);
266  goto exit;
267  }
268 
269  amxc_llist_append(&dm->deferred, &call_ctx->dm_it);
270  }
271 
272 exit:
273  return retval;
274 }
275 
277  amxd_dm_access_t access) {
278  uint32_t count = 0;
279  amxc_var_t funcs;
280  const amxc_llist_t* funcs_list = NULL;
281 
282  when_null(object, exit);
283 
284  amxc_var_init(&funcs);
285  amxd_object_list_functions(object, &funcs, access);
286  funcs_list = amxc_var_constcast(amxc_llist_t, &funcs);
287  count = amxc_llist_size(funcs_list);
288  amxc_var_clean(&funcs);
289 
290 exit:
291  return count;
292 }
Ambiorix Data Model Default actions header file.
amxd_deferred_ctx_t *PRIVATE amxd_find_deferred(uint64_t call_id)
Ambiorix Data Model RPC methods API header file.
Ambiorix Data Model API header file.
static bool amxd_object_can_invoke_function(const amxd_object_t *const object, const amxd_function_t *const func)
static amxd_status_t amxd_object_invoke_check(amxd_object_t *const object, amxd_function_t **func, const char *func_name, amxc_var_t *const args)
static int is_brace(int c)
static void amxd_function_remove_in_args(amxd_function_t *func, amxc_var_t *args)
PRIVATE amxd_function_t * amxd_object_get_self_func(const amxd_object_t *const object, const char *name)
enum _amxd_status amxd_status_t
amxd_status_t(* amxd_object_fn_t)(amxd_object_t *object, amxd_function_t *func, amxc_var_t *args, amxc_var_t *ret)
Definition: amxd_types.h:272
@ amxd_status_invalid_name
Definition: amxd_types.h:86
@ amxd_status_function_not_implemented
Definition: amxd_types.h:83
@ amxd_status_invalid_function
Definition: amxd_types.h:84
@ amxd_status_invalid_function_argument
Definition: amxd_types.h:85
@ amxd_status_ok
Definition: amxd_types.h:78
@ amxd_status_unknown_error
Definition: amxd_types.h:79
@ amxd_status_deferred
Definition: amxd_types.h:92
@ amxd_status_function_not_found
Definition: amxd_types.h:81
@ amxd_status_duplicate
Definition: amxd_types.h:91
enum _amxd_dm_access amxd_dm_access_t
Access level.
@ amxd_oattr_locked
Definition: amxd_types.h:206
@ amxd_object_template
Definition: amxd_types.h:183
@ amxd_object_instance
Definition: amxd_types.h:186
amxd_object_t * amxd_object_get_parent(const amxd_object_t *const object)
Get the parent object.
amxd_dm_t * amxd_object_get_dm(const amxd_object_t *const object)
Get the data model.
amxd_status_t amxd_object_change_function(amxd_object_t *const object, const char *name, amxd_object_fn_t impl)
Changes the implementation of an object's RPC method.
amxd_status_t amxd_object_add_function(amxd_object_t *const object, amxd_function_t *const func)
Adds an RPC method definition to the object definition.
amxd_function_t * amxd_object_get_function(const amxd_object_t *const object, const char *name)
Get the definition of a RPC method from an object.
uint32_t amxd_object_get_function_count(amxd_object_t *const object, amxd_dm_access_t access)
Retruns the number of RPC methods available in an object.
amxd_status_t amxd_object_list_functions(amxd_object_t *const object, amxc_var_t *const list, amxd_dm_access_t access)
Builds a linked list variant containing all function names available in the object.
amxd_status_t amxd_object_invoke_function(amxd_object_t *const object, const char *func_name, amxc_var_t *const args, amxc_var_t *const ret)
Calls an object RPC method.
static amxd_object_type_t amxd_object_get_type(const amxd_object_t *const object)
Returns the object type.
Definition: amxd_object.h:586
bool amxd_object_is_attr_set(const amxd_object_t *const object, const amxd_oattr_id_t attr)
Checks if an attribute is set.
Definition: amxd_object.c:348
const char * amxd_function_get_name(const amxd_function_t *const func)
Get the name of a method.
amxd_object_t * amxd_function_get_owner(const amxd_function_t *const func)
Get the object pointer of the object containing the function definition.
amxd_status_t amxd_function_copy(amxd_function_t **dest, const amxd_function_t *const source)
Data model RPC method copy constructor function.
bool amxd_function_are_args_valid(amxd_function_t *func, amxc_var_t *args)
Validates that the input arguments are valid.
uint32_t out
Definition: amxd_types.h:292
amxc_llist_it_t dm_it
Definition: amxd_dm_priv.h:64
amxc_llist_t deferred
Definition: amxd_types.h:264
amxd_arg_attr_t attr
Definition: amxd_types.h:299
uint32_t templ
Definition: amxd_types.h:326
uint32_t instance
Definition: amxd_types.h:327
RPC method structure.
Definition: amxd_types.h:341
amxc_llist_t args
Definition: amxd_types.h:346
amxc_llist_it_t it
Definition: amxd_types.h:342
amxd_object_fn_t impl
Definition: amxd_types.h:347
amxd_func_attr_t attr
Definition: amxd_types.h:343
amxc_llist_it_t derived_from
Definition: amxd_types.h:249
amxc_llist_t functions
Definition: amxd_types.h:245
static amxd_dm_t dm
static uint64_t call_id