libamxd  6.4.1
Data Model Manager
amxd_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 <amxc/amxc.h>
64 
65 #include <amxp/amxp_signal.h>
66 #include <amxp/amxp_slot.h>
67 
68 #include <amxd/amxd_common.h>
69 #include <amxd/amxd_types.h>
70 #include <amxd/amxd_object.h>
71 #include <amxd/amxd_function.h>
72 
73 #include "amxd_priv.h"
74 #include "amxd_assert.h"
75 #include "amxd_dm_priv.h"
76 
77 static void amxd_function_free_arg_it(amxc_llist_it_t* it) {
78  amxd_func_arg_t* arg = amxc_llist_it_get_data(it, amxd_func_arg_t, it);
80  free(arg);
81 }
82 
84  const char* name,
85  uint32_t ret_type,
86  amxd_object_fn_t impl) {
88 
89  amxc_llist_it_init(&func->it);
90 
91  func->attr.templ = 0;
92  func->attr.instance = 0;
93  func->attr.priv = 0;
94  func->attr.prot = 0;
95 
96  if((ret_type == AMXC_VAR_ID_ANY) ||
97  ( amxc_var_get_type(ret_type) != NULL)) {
98  func->name = strdup(name);
99  when_null(func->name, exit);
100 
101  amxc_llist_init(&func->args);
102  func->ret_type = ret_type;
103  func->impl = impl;
104 
105  retval = amxd_status_ok;
106  }
107 
108 exit:
109  return retval;
110 }
111 
112 static int amxd_function_clean(amxd_function_t* const func) {
113  amxc_llist_it_take(&func->it);
114  amxc_llist_clean(&func->args, amxd_function_free_arg_it);
115  amxc_var_delete(&func->flags);
116 
117  free(func->name);
118  func->name = NULL;
119  func->impl = NULL;
120 
121  return 0;
122 }
123 
124 static uint32_t amxd_function_get_attributes(const amxd_function_t* const func) {
125 
126  uint32_t attributes = 0;
127 
128  attributes |= func->attr.templ << amxd_fattr_template;
129  attributes |= func->attr.instance << amxd_fattr_instance;
130  attributes |= func->attr.priv << amxd_fattr_private;
131  attributes |= func->attr.prot << amxd_fattr_protected;
132  attributes |= func->attr.async << amxd_fattr_async;
133 
134  return attributes;
135 }
136 
138  const uint32_t attr) {
139  func->attr.templ = IS_BIT_SET(attr, amxd_fattr_template);
141  func->attr.priv = IS_BIT_SET(attr, amxd_fattr_private);
142  func->attr.prot = IS_BIT_SET(attr, amxd_fattr_protected);
143  func->attr.async = IS_BIT_SET(attr, amxd_fattr_async);
144 }
145 
147  const char* name,
148  const uint32_t ret_type,
149  amxd_object_fn_t impl) {
151  when_null(func, exit);
152  when_true_status(!amxd_name_is_valid(name),
153  exit,
154  retval = amxd_status_invalid_name);
155 
156  *func = (amxd_function_t*) calloc(1, sizeof(amxd_function_t));
157  when_null((*func), exit);
158 
159  retval = amxd_function_init(*func, name, ret_type, impl);
160 
161 exit:
162  if((retval != 0) && (func != NULL)) {
163  free(*func);
164  *func = NULL;
165  }
166  return retval;
167 }
168 
170  when_null(func, exit);
171  when_null((*func), exit);
172 
173  amxd_function_clean((*func));
174  free(*func);
175  *func = NULL;
176 
177 exit:
178  return;
179 }
180 
182  const amxd_function_t* const source) {
184  when_null(dest, exit);
185  when_null(source, exit);
186 
187  *dest = (amxd_function_t*) calloc(1, sizeof(amxd_function_t));
188  when_null((*dest), exit);
189 
190  when_failed(amxd_function_init(*dest, source->name,
191  source->ret_type,
192  source->impl), exit);
193  (*dest)->attr = source->attr;
194 
195  amxc_llist_for_each(it, (&source->args)) {
196  amxd_func_arg_t* arg = amxc_llist_it_get_data(it, amxd_func_arg_t, it);
197  when_failed(amxd_function_new_arg((*dest),
198  arg->name,
199  arg->type,
200  &arg->default_value), exit);
202  amxd_function_arg_set_attr((*dest), arg->name, amxd_aattr_in, true);
203  }
205  amxd_function_arg_set_attr((*dest), arg->name, amxd_aattr_out, true);
206  }
209  }
211  amxd_function_arg_set_attr((*dest), arg->name, amxd_aattr_strict, true);
212  }
213  }
214 
215  retval = amxd_status_ok;
216 
217 exit:
218  if((retval != amxd_status_ok) && (dest != NULL) && (*dest != NULL)) {
219  amxd_function_clean(*dest);
220  free(*dest);
221  *dest = NULL;
222  }
223  return retval;
224 }
225 
227  amxd_object_t* object = NULL;
228  when_null(func, exit);
229  when_null(func->it.llist, exit);
230 
231  object = amxc_container_of(func->it.llist, amxd_object_t, functions);
232 
233 exit:
234  return object;
235 }
236 
238  amxd_function_t* base = NULL;
239  amxd_object_t* object = amxd_function_get_owner(func);
240 
241  when_null(object, exit);
242 
245  func->name);
246  } else {
247  if(amxc_llist_it_is_in_list(&object->derived_from)) {
248  amxd_object_t* super = NULL;
249  super = amxc_container_of(object->derived_from.llist,
251  derived_objects);
252  base = amxd_object_get_function(super, func->name);
253  }
254  }
255 
256 exit:
257  return base;
258 }
259 
261  amxd_object_t* const object,
262  amxc_var_t* const args,
263  amxc_var_t* const ret) {
265  amxd_function_t* base_func = amxd_function_get_base(func);
266 
267  when_null(object, exit);
268  when_null(base_func, exit);
269  if(base_func->impl == NULL) {
271  goto exit;
272  }
273  status = base_func->impl(object, base_func, args, ret);
274 
275 exit:
276  return status;
277 }
278 
279 const char* amxd_function_get_name(const amxd_function_t* const func) {
280  return func == NULL ? NULL : func->name;
281 }
282 
284  const amxd_fattr_id_t attr,
285  const bool enable) {
287  uint32_t flags = 0;
288  when_null(func, exit);
289 
290  when_true_status(attr < 0 || attr > amxd_fattr_max,
291  exit,
292  retval = amxd_status_invalid_attr);
293 
294  flags = amxd_function_get_attributes(func);
295 
296  if(enable) {
297  flags |= (1 << attr);
298  } else {
299  flags &= ~(1 << attr);
300  }
301 
302  amxd_function_set_attributes(func, flags);
303 
304  retval = amxd_status_ok;
305 
306 exit:
307  return retval;
308 }
309 
311  const uint32_t bitmask,
312  bool enable) {
314  uint32_t flags = 0;
315  uint32_t all = 0;
316 
317  for(int i = 0; i <= amxd_fattr_max; i++) {
318  all |= SET_BIT(i);
319  }
320 
321  when_null(func, exit);
322  when_true_status(bitmask > all, exit, retval = amxd_status_invalid_attr);
323 
324  flags = amxd_function_get_attributes(func);
325 
326  if(enable) {
327  flags |= bitmask;
328  } else {
329  flags &= ~bitmask;
330  }
331 
332  amxd_function_set_attributes(func, flags);
333  retval = amxd_status_ok;
334 
335 exit:
336  return retval;
337 }
338 
339 uint32_t amxd_function_get_attrs(const amxd_function_t* const func) {
340  uint32_t attributes = 0;
341  when_null(func, exit);
342 
343  attributes |= func->attr.templ << amxd_fattr_template;
344  attributes |= func->attr.instance << amxd_fattr_instance;
345  attributes |= func->attr.priv << amxd_fattr_private;
346  attributes |= func->attr.prot << amxd_fattr_protected;
347  attributes |= func->attr.async << amxd_fattr_async;
348 
349 exit:
350  return attributes;
351 }
352 
354  const amxd_fattr_id_t attr) {
355  uint32_t flags = 0;
356  bool retval = false;
357  when_null(func, exit);
358  when_true(attr < 0 || attr > amxd_fattr_max, exit);
359 
360  flags = amxd_function_get_attributes(func);
361  retval = (flags & (1 << attr)) != 0 ? true : false;
362 
363 exit:
364  return retval;
365 }
366 
367 void amxd_function_set_flag(amxd_function_t* func, const char* flag) {
368  when_null(func, exit);
369  when_null(flag, exit);
370  when_true(*flag == 0, exit);
371 
372  amxd_common_set_flag(&func->flags, flag);
373 
374 exit:
375  return;
376 }
377 
378 void amxd_function_unset_flag(amxd_function_t* func, const char* flag) {
379  when_null(func, exit);
380  when_null(flag, exit);
381  when_true(*flag == 0, exit);
382 
383  amxd_common_unset_flag(&func->flags, flag);
384 
385 exit:
386  return;
387 }
388 
389 bool amxd_function_has_flag(const amxd_function_t* const func, const char* flag) {
390  bool retval = false;
391  when_null(func, exit);
392  when_null(flag, exit);
393  when_true(*flag == 0, exit);
394 
395  retval = amxd_common_has_flag(func->flags, flag);
396 
397 exit:
398  return retval;
399 }
400 
402  amxd_object_fn_t impl) {
404  when_null(func, exit);
405 
406  func->impl = impl;
407  retval = amxd_status_ok;
408 
409 exit:
410  return retval;
411 }
412 
414  amxc_var_t* const value) {
416  amxc_var_t* table = NULL;
417  uint32_t retvalt = 0;
418 
419  static const char* attr_name[] = {
420  "template",
421  "instance",
422  "private",
423  "protected",
424  "asynchronous",
425  };
426 
427  when_null(func, exit);
428  when_null(value, exit);
429 
430  retvalt = amxd_function_get_type(func);
431  amxc_var_set_type(value, AMXC_VAR_ID_HTABLE);
432  amxc_var_add_key(cstring_t, value, "name", amxd_function_get_name(func));
433  amxc_var_add_key(uint32_t, value, "type_id", retvalt);
434  amxc_var_add_key(cstring_t,
435  value,
436  "type_name",
437  amxc_var_get_type_name_from_id(retvalt));
438  table = amxc_var_add_key(amxc_htable_t, value, "attributes", NULL);
439  for(int i = 0; i <= (int) amxd_fattr_max; i++) {
440  amxc_var_add_key(bool,
441  table,
442  attr_name[i],
444  }
445 
446  table = amxc_var_add_key(amxc_llist_t, value, "arguments", NULL);
447  amxc_llist_for_each(it, (&func->args)) {
448  amxd_func_arg_t* farg = amxc_llist_it_get_data(it, amxd_func_arg_t, it);
449  amxc_var_t* arg = amxc_var_add(amxc_htable_t, table, NULL);
450  amxd_function_arg_describe(farg, arg);
451  }
452 
453  table = amxc_var_add_key(amxc_llist_t, value, "flags", NULL);
454  if(func->flags != NULL) {
455  amxc_var_for_each(flag, func->flags) {
456  if(amxc_var_dyncast(bool, flag)) {
457  amxc_var_add(cstring_t, table, amxc_var_key(flag));
458  }
459  }
460  }
461 
463 
464 exit:
465  return status;
466 }
467 
469  const char* name) {
470  amxd_func_arg_t* arg = NULL;
471  when_null(func, exit);
472  when_str_empty(name, exit);
473 
474  amxc_llist_for_each(it, (&func->args)) {
475  arg = amxc_llist_it_get_data(it, amxd_func_arg_t, it);
476  if(strcmp(arg->name, name) == 0) {
477  break;
478  }
479  arg = NULL;
480  }
481 
482 exit:
483  return arg;
484 }
485 
487  amxc_var_t* args) {
488  bool valid = false;
489 
490  when_null(func, exit);
491  when_null(args, exit);
492  when_false(amxc_var_type_of(args) == AMXC_VAR_ID_HTABLE, exit);
493 
494  amxc_llist_for_each(it, (&func->args)) {
495  amxd_func_arg_t* arg = amxc_llist_it_get_data(it, amxd_func_arg_t, it);
496  amxc_var_t* in_arg = amxc_var_get_key(args,
497  arg->name,
498  AMXC_VAR_FLAG_DEFAULT);
499  if(arg->attr.in == 0) {
500  continue;
501  }
502  if(arg->attr.mandatory == 1) {
503  when_null(in_arg, exit);
504  }
505  if((in_arg == NULL) &&
506  ( amxc_var_type_of(&arg->default_value) != AMXC_VAR_ID_NULL)) {
507  in_arg = amxc_var_add_new_key(args, arg->name);
508  amxc_var_copy(in_arg, &arg->default_value);
509  }
510  if((arg->attr.strict == 1) &&
511  ( in_arg != NULL)) {
512  when_true(arg->type != amxc_var_type_of(in_arg), exit);
513  }
514  }
515 
516  valid = true;
517 
518 exit:
519  return valid;
520 }
#define IS_BIT_SET(b, f)
Definition: amxd_common.h:66
bool amxd_name_is_valid(const char *name)
Definition: amxd_common.c:115
#define SET_BIT(x)
Definition: amxd_common.h:65
bool PRIVATE amxd_common_has_flag(const amxc_var_t *const flags, const char *flag)
Definition: amxd_dm_priv.c:652
void PRIVATE amxd_common_set_flag(amxc_var_t **flags, const char *flag)
Definition: amxd_dm_priv.c:617
void PRIVATE amxd_common_unset_flag(amxc_var_t **flags, const char *flag)
Definition: amxd_dm_priv.c:634
static void amxd_function_free_arg_it(amxc_llist_it_t *it)
Definition: amxd_function.c:77
static void amxd_function_set_attributes(amxd_function_t *const func, const uint32_t attr)
static uint32_t amxd_function_get_attributes(const amxd_function_t *const func)
static amxd_status_t amxd_function_init(amxd_function_t *const func, const char *name, uint32_t ret_type, amxd_object_fn_t impl)
Definition: amxd_function.c:83
static int amxd_function_clean(amxd_function_t *const func)
Ambiorix Data Model RPC methods API header file.
Ambiorix Data Model API header file.
void PRIVATE amxd_function_arg_clean(amxd_func_arg_t *const arg)
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_invalid_attr
Definition: amxd_types.h:87
@ amxd_status_function_not_implemented
Definition: amxd_types.h:83
@ amxd_status_ok
Definition: amxd_types.h:78
@ amxd_status_unknown_error
Definition: amxd_types.h:79
enum _amxd_fattr_id amxd_fattr_id_t
The method attributes.
@ amxd_fattr_max
Definition: amxd_types.h:322
@ amxd_fattr_template
Definition: amxd_types.h:311
@ amxd_fattr_async
Definition: amxd_types.h:321
@ amxd_fattr_private
Definition: amxd_types.h:313
@ amxd_fattr_protected
Definition: amxd_types.h:317
@ amxd_fattr_instance
Definition: amxd_types.h:312
@ amxd_aattr_strict
Definition: amxd_types.h:286
@ amxd_aattr_in
Definition: amxd_types.h:283
@ amxd_aattr_mandatory
Definition: amxd_types.h:285
@ amxd_aattr_out
Definition: amxd_types.h:284
@ 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_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.
static amxd_object_type_t amxd_object_get_type(const amxd_object_t *const object)
Returns the object type.
Definition: amxd_object.h:586
amxd_status_t amxd_function_set_attr(amxd_function_t *func, const amxd_fattr_id_t attr, const bool enable)
Sets or unsets a method attribute.
amxd_status_t amxd_function_describe(amxd_function_t *const func, amxc_var_t *const value)
Fetches the full RPC method definition in a variant.
const char * amxd_function_get_name(const amxd_function_t *const func)
Get the name of a method.
void amxd_function_delete(amxd_function_t **func)
Data model RPC method destructor function.
amxd_status_t amxd_function_arg_set_attr(amxd_function_t *const func, const char *name, const amxd_aattr_id_t attr, const bool enable)
Sets or unsets a method argument attribute.
amxd_func_arg_t * amxd_function_get_arg(const amxd_function_t *const func, const char *name)
Gets the argument definition of a RPC method.
bool amxd_function_arg_is_attr_set(const amxd_function_t *const func, const char *name, const amxd_aattr_id_t attr)
Checks if a method argument attribute is set.
amxd_status_t amxd_function_arg_describe(amxd_func_arg_t *const arg, amxc_var_t *const value)
Fetches the argument definition in a variant.
amxd_object_t * amxd_function_get_owner(const amxd_function_t *const func)
Get the object pointer of the object containing the function definition.
static uint32_t amxd_function_get_type(const amxd_function_t *const func)
Gets the return type of a method.
void amxd_function_unset_flag(amxd_function_t *func, const char *flag)
Removes a flag from a function.
amxd_status_t amxd_function_new(amxd_function_t **func, const char *name, const uint32_t ret_type, amxd_object_fn_t impl)
Data model RPC method constructor function.
amxd_status_t amxd_function_call_base(const amxd_function_t *const func, amxd_object_t *const object, amxc_var_t *const args, amxc_var_t *const ret)
Call the base function of an overridden function.
amxd_status_t amxd_function_set_attrs(amxd_function_t *func, const uint32_t bitmask, bool enable)
Sets or unsets method attributes using a bitmap.
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.
bool amxd_function_is_attr_set(const amxd_function_t *const func, const amxd_fattr_id_t attr)
Checks if a method attribute is set.
bool amxd_function_has_flag(const amxd_function_t *const func, const char *flag)
Checks if a flag is set.
void amxd_function_set_flag(amxd_function_t *func, const char *flag)
Sets a flag on a function.
uint32_t amxd_function_get_attrs(const amxd_function_t *const func)
Gets the set attributes of a RPC method.
amxd_function_t * amxd_function_get_base(const amxd_function_t *const func)
Get the base function definition of an overridden function.
amxd_status_t amxd_function_new_arg(amxd_function_t *func, const char *name, const uint32_t type, amxc_var_t *default_value)
Adds an argument definition to a RPC method definition.
amxd_status_t amxd_function_set_impl(amxd_function_t *const func, amxd_object_fn_t impl)
Set an implementation for a RPC method.
uint32_t in
Definition: amxd_types.h:291
uint32_t strict
Definition: amxd_types.h:294
uint32_t mandatory
Definition: amxd_types.h:293
amxc_var_t default_value
Definition: amxd_types.h:302
uint32_t type
Definition: amxd_types.h:301
amxd_arg_attr_t attr
Definition: amxd_types.h:299
uint32_t templ
Definition: amxd_types.h:326
uint32_t priv
Definition: amxd_types.h:329
uint32_t async
Definition: amxd_types.h:331
uint32_t prot
Definition: amxd_types.h:330
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
uint32_t ret_type
Definition: amxd_types.h:345
amxc_var_t * flags
Definition: amxd_types.h:348
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
static amxd_status_t status