libamxo  4.3.4
Object Definition Language (ODL) parsing
amxo_parser_dm_param_utils.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 #ifndef _GNU_SOURCE
55 #define _GNU_SOURCE
56 #endif
57 
58 #include "amxo_parser_priv.h"
59 #include "amxo_parser.tab.h"
60 #include "amxo_parser_hooks_priv.h"
61 
62 static int64_t amxo_attr_2_param_attr(int64_t attributes) {
63  int64_t param_attrs = 0;
64  if(SET_BIT(attr_readonly) & attributes) {
65  param_attrs |= SET_BIT(amxd_pattr_read_only);
66  }
67  if(SET_BIT(attr_persistent) & attributes) {
68  param_attrs |= SET_BIT(amxd_pattr_persistent);
69  }
70  if(SET_BIT(attr_private) & attributes) {
71  param_attrs |= SET_BIT(amxd_pattr_private);
72  }
73  if(SET_BIT(attr_protected) & attributes) {
74  param_attrs |= SET_BIT(amxd_pattr_protected);
75  }
76  if(SET_BIT(attr_template) & attributes) {
77  param_attrs |= SET_BIT(amxd_pattr_template);
78  }
79  if(SET_BIT(attr_instance) & attributes) {
80  param_attrs |= SET_BIT(amxd_pattr_instance);
81  }
82  if(SET_BIT(attr_variable) & attributes) {
83  param_attrs |= SET_BIT(amxd_pattr_variable);
84  }
85  if(SET_BIT(attr_key) & attributes) {
86  param_attrs |= SET_BIT(amxd_pattr_key);
87  }
88  if(SET_BIT(attr_unique) & attributes) {
89  param_attrs |= SET_BIT(amxd_pattr_unique);
90  }
91  if(SET_BIT(attr_mutable) & attributes) {
92  param_attrs |= SET_BIT(amxd_pattr_mutable);
93  }
94  return param_attrs;
95 }
96 
98  event_id_t event) {
99  amxc_lstack_it_t* it = amxc_llist_get_last(&pctx->event_list);
100  event_t* e = amxc_container_of(it, event_t, it);
101  e->id = event;
102 }
103 
105  amxd_param_t* param) {
106  amxc_lstack_it_t* it = amxc_llist_get_last(&pctx->event_list);
107  event_t* e = amxc_container_of(it, event_t, it);
108  amxc_var_t* value = NULL;
109 
110  when_true(e->id != event_object_change, exit);
111  if(amxc_var_type_of(&e->data) != AMXC_VAR_ID_HTABLE) {
112  amxc_var_set_type(&e->data, AMXC_VAR_ID_HTABLE);
113  }
114  value = GET_ARG(&e->data, amxd_param_get_name(param));
115  when_not_null(value, exit);
116 
117  amxc_var_set_key(&e->data, amxd_param_get_name(param), &param->value, AMXC_VAR_FLAG_COPY);
118 
119 exit:
120  return;
121 }
122 
123 static amxd_param_t* amxo_parser_new_param(amxo_parser_t* pctx,
124  const char* name,
125  int64_t pattrs,
126  uint32_t type) {
127  amxd_param_t* param = NULL;
128 
129  pctx->status = amxd_param_new(&param, name, type);
130  if(pctx->status != amxd_status_ok) {
131  amxo_parser_msg(pctx, "Failed to create parameter %s", name);
132  goto exit;
133  }
134  amxd_param_set_attrs(param, pattrs, true);
135  pctx->status = amxd_object_add_param(pctx->object, param);
136 
137 exit:
138  return param;
139 }
140 
142  const char* parent_path,
143  const char* name,
144  amxd_param_t* param,
145  amxc_var_t* value) {
146  int retval = -1;
147  if((value != NULL) && (param != NULL)) {
148  if((amxc_var_type_of(value) == AMXC_VAR_ID_HTABLE) ||
149  (amxc_var_type_of(value) == AMXC_VAR_ID_LIST)) {
150  pctx->status = amxd_status_invalid_value;
151  } else {
152  pctx->status = amxd_param_set_value(param, value);
153  }
154  if(pctx->status == amxd_status_invalid_value) {
155  amxo_parser_msg(pctx,
156  "Invalid parameter value for parameter %s in object \"%s\"",
157  name,
158  parent_path);
159  } else if(pctx->status == amxd_status_ok) {
160  pctx->param = param;
161  amxo_hooks_set_param(pctx, value);
162  retval = 0;
163  }
164  } else {
165  pctx->param = param;
166  if(param != NULL) {
167  retval = 0;
168  amxo_hooks_set_param(pctx, value);
169  }
170  }
171 
172  return retval;
173 }
174 
176  const char* name,
177  int64_t pattrs,
178  uint32_t type) {
179  bool retval = false;
180  amxd_param_t* param = NULL;
181 
182  if(amxd_object_get_type(pctx->object) == amxd_object_instance) {
183  pattrs |= SET_BIT(amxd_pattr_instance);
184  }
185  param = amxo_parser_new_param(pctx, name, pattrs, type);
186  when_null(param, exit);
187  amxo_hooks_add_param(pctx, name, pattrs, type);
188 
189  pctx->param = param;
190  retval = true;
191 
192 exit:
193  return retval;
194 }
195 
197  amxd_param_t* param,
198  const char* name,
199  uint32_t type) {
200  bool retval = false;
201 
202  if(!amxo_parser_check_config(pctx,
203  "define-behavior.existing-parameter",
204  "update")) {
205  amxo_parser_msg(pctx, "Duplicate parameter %s", name);
206  pctx->status = amxd_status_duplicate;
207  goto exit;
208  }
209  if((type != AMXC_VAR_ID_LIST) &&
210  ( type != AMXC_VAR_ID_HTABLE) &&
211  ( type != AMXC_VAR_ID_FD)) {
212  amxc_var_set_type(&param->value, type);
213  } else {
214  amxo_parser_msg(pctx, "Invalid parameter type for parameter %s", name);
215  pctx->status = amxd_status_invalid_type;
216  goto exit;
217  }
218 
219  pctx->param = param;
220  retval = true;
221 
222 exit:
223  return retval;
224 }
225 
226 static amxd_param_t* amxo_parser_check_param(amxo_parser_t* pctx,
227  const char* name,
228  const char* parent_path,
229  amxc_var_t* value,
230  int* retval) {
231  amxd_param_t* param = NULL;
232  if(amxo_parser_check_config(pctx, "populate-behavior.unknown-parameter", "add")) {
233  uint32_t type = amxc_var_is_null(value) ? AMXC_VAR_ID_CSTRING : amxc_var_type_of(value);
234  int64_t pattrs = SET_BIT(amxd_pattr_persistent);
235  if(amxd_object_get_type(pctx->object) == amxd_object_instance) {
236  pattrs |= SET_BIT(amxd_pattr_instance);
237  }
238  if(amxd_object_get_type(pctx->object) == amxd_object_template) {
239  pattrs |= SET_BIT(amxd_pattr_instance);
240  pattrs |= SET_BIT(amxd_pattr_template);
241  }
242  param = amxo_parser_new_param(pctx, name, pattrs, type);
243  } else if(amxo_parser_check_config(pctx,
244  "populate-behavior.unknown-parameter",
245  "warning")) {
246  amxo_parser_msg(pctx,
247  "Parameter %s not found in object \"%s\"",
248  name,
249  parent_path);
250  pctx->status = amxd_status_parameter_not_found;
251  *retval = 0;
252  } else {
253  amxo_parser_msg(pctx,
254  "Parameter %s not found in object \"%s\"",
255  name,
256  parent_path);
257  pctx->status = amxd_status_parameter_not_found;
258  }
259 
260  return param;
261 }
262 
263 bool amxo_parser_set_param_attrs(amxo_parser_t* pctx, uint64_t attr, bool enable) {
264  int64_t pattrs = amxo_attr_2_param_attr(attr);
265  amxd_param_set_attrs(pctx->param, pattrs, enable);
266  return true;
267 }
268 
269 bool amxo_parser_set_param_flags(amxo_parser_t* pctx, amxc_var_t* flags) {
270  const amxc_htable_t* ht_flags = NULL;
271 
272  when_null(flags, exit);
273  when_true(amxc_var_type_of(flags) != AMXC_VAR_ID_HTABLE, exit);
274 
275  ht_flags = amxc_var_constcast(amxc_htable_t, flags);
276  amxc_htable_for_each(it, ht_flags) {
277  const char* flag_name = amxc_htable_it_get_key(it);
278  amxc_var_t* flag = amxc_var_from_htable_it(it);
279  if(amxc_var_dyncast(bool, flag)) {
280  amxd_param_set_flag(pctx->param, flag_name);
281  } else {
282  amxd_param_unset_flag(pctx->param, flag_name);
283  }
284  }
285 
286  amxc_var_delete(&flags);
287 
288 exit:
289  return true;
290 }
291 
293  const char* name,
294  int64_t attr_bitmask,
295  uint32_t type) {
296  amxd_param_t* param = NULL;
297  int64_t pattrs = amxo_attr_2_param_attr(attr_bitmask);
298  bool retval = false;
299  amxc_string_t res_name;
300  amxc_string_init(&res_name, 0);
301 
303 
304  if(amxc_string_set_resolved(&res_name, name, &pctx->config) > 0) {
305  name = amxc_string_get(&res_name, 0);
306  }
307 
308  pctx->status = amxd_status_ok;
309  param = amxd_object_get_param_def(pctx->object, name);
310  if(param == NULL) {
311  retval = amxo_parser_add_param(pctx, name, pattrs, type);
312  } else {
313  retval = amxo_parser_update_param(pctx, param, name, type);
314  }
315 
316  amxc_string_clean(&res_name);
317  return retval;
318 }
319 
321  const char* name,
322  amxc_var_t* value) {
323  amxd_param_t* param = NULL;
324  int retval = -1;
325  char* parent_path = amxd_object_get_path(pctx->object, AMXD_OBJECT_NAMED);
326  amxc_string_t res_name;
327  amxc_string_init(&res_name, 0);
328 
329  if(amxc_string_set_resolved(&res_name, name, &pctx->config) > 0) {
330  name = amxc_string_get(&res_name, 0);
331  }
332 
333  pctx->status = amxd_status_ok;
334  param = pctx->param == NULL ? amxd_object_get_param_def(pctx->object, name) : pctx->param;
335  if(param == NULL) {
336  param = amxo_parser_check_param(pctx, name, parent_path, value, &retval);
337  }
338  if(param != NULL) {
339  amxo_parser_data_event(pctx, param);
340  retval = amxo_parser_set_param_value(pctx, parent_path, name, param, value);
341  }
342 
343  amxc_string_clean(&res_name);
344  free(parent_path);
345  return retval;
346 }
347 
349  bool retval = false;
350  amxc_var_t value;
351  amxc_var_init(&value);
352 
353  if(pctx->param != NULL) {
354  amxc_var_copy(&value, &pctx->param->value);
355  pctx->status = amxd_param_validate(pctx->param, &value);
356  if(pctx->status != amxd_status_ok) {
357  amxo_parser_msg(pctx, "Parameter %s validation failed",
358  amxd_param_get_name(pctx->param));
359  goto exit;
360  }
361 
362  amxo_hooks_end_param(pctx);
363  pctx->param = NULL;
364  }
365  retval = true;
366 
367 exit:
368  amxc_var_clean(&value);
369  return retval;
370 }
bool amxo_parser_set_param_flags(amxo_parser_t *pctx, amxc_var_t *flags)
bool amxo_parser_set_param_attrs(amxo_parser_t *pctx, uint64_t attr, bool enable)
static bool amxo_parser_add_param(amxo_parser_t *pctx, const char *name, int64_t pattrs, uint32_t type)
int amxo_parser_set_param(amxo_parser_t *pctx, const char *name, amxc_var_t *value)
bool amxo_parser_pop_param(amxo_parser_t *pctx)
static amxd_param_t * amxo_parser_new_param(amxo_parser_t *pctx, const char *name, int64_t pattrs, uint32_t type)
static void amxo_parser_data_event(amxo_parser_t *pctx, amxd_param_t *param)
static amxd_param_t * amxo_parser_check_param(amxo_parser_t *pctx, const char *name, const char *parent_path, amxc_var_t *value, int *retval)
static int amxo_parser_set_param_value(amxo_parser_t *pctx, const char *parent_path, const char *name, amxd_param_t *param, amxc_var_t *value)
static void amxo_parser_set_event(amxo_parser_t *pctx, event_id_t event)
bool amxo_parser_push_param(amxo_parser_t *pctx, const char *name, int64_t attr_bitmask, uint32_t type)
static bool amxo_parser_update_param(amxo_parser_t *pctx, amxd_param_t *param, const char *name, uint32_t type)
static int64_t amxo_attr_2_param_attr(int64_t attributes)
PRIVATE void amxo_hooks_add_param(amxo_parser_t *parser, const char *name, int64_t attr_bitmask, uint32_t type)
PRIVATE void amxo_hooks_set_param(amxo_parser_t *parser, amxc_var_t *value)
PRIVATE void amxo_hooks_end_param(amxo_parser_t *parser)
@ attr_instance
@ attr_variable
@ attr_protected
@ attr_template
@ attr_persistent
@ attr_readonly
@ attr_private
@ attr_key
@ attr_unique
@ attr_mutable
PRIVATE bool amxo_parser_check_config(amxo_parser_t *pctx, const char *path, const char *check)
PRIVATE void amxo_parser_msg(amxo_parser_t *parser, const char *format,...) __attribute__((format(printf
enum _event_id event_id_t
@ event_object_change
@ event_none
The ODL parser structure.
Definition: amxo_types.h:245
amxc_lstack_t event_list
Definition: amxo_types.h:283
amxd_param_t * param
Definition: amxo_types.h:263
amxc_var_t config
Definition: amxo_types.h:250
amxd_status_t status
Definition: amxo_types.h:258
amxd_object_t * object
Definition: amxo_types.h:262
event_id_t id
amxc_var_t data