libamxd  6.4.1
Data Model Manager
amxd_object_expression.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 
62 #include <amxc/amxc.h>
63 #include <amxp/amxp_signal.h>
64 #include <amxp/amxp_slot.h>
65 #include <amxp/amxp_expression.h>
66 
67 #include <amxd/amxd_types.h>
68 #include <amxd/amxd_object.h>
69 #include <amxd/amxd_path.h>
71 #include <amxd/amxd_dm.h>
72 
73 #include "amxd_priv.h"
74 #include "amxd_dm_priv.h"
75 #include "amxd_object_priv.h"
76 #include "amxd_assert.h"
77 
78 static char* amxd_key_expr_get_value(const amxc_htable_t* const data,
79  const char* name) {
80  char* value = NULL;
81  amxc_htable_it_t* hit = NULL;
82  amxc_var_t* ht_data = NULL;
83 
84  hit = amxc_htable_get(data, name);
85  when_null(hit, exit);
86  ht_data = amxc_var_from_htable_it(hit);
87  value = amxc_var_dyncast(cstring_t, ht_data);
88 
89 exit:
90  return value;
91 }
92 
93 static amxd_status_t amxd_build_key_expr_string(amxc_var_t* const templ_params,
94  const amxc_htable_t* const data,
95  amxc_string_t* str_expr) {
97  const amxc_htable_t* ht_params = NULL;
98  const char* unique_lop = ")";
99  const char* key_lop = "(";
100 
101  ht_params = amxc_var_constcast(amxc_htable_t, templ_params);
102  amxc_htable_for_each(it, ht_params) {
103  const char* name = amxc_htable_it_get_key(it);
104  amxc_var_t* param = amxc_var_from_htable_it(it);
105  char* value = NULL;
106  if(!amxc_var_constcast(bool, GET_FIELD(param, "attributes.key"))) {
107  continue;
108  }
109  value = amxd_key_expr_get_value(data, name);
110  when_null_status(value, exit, status = amxd_status_missing_key);
111  if(amxc_var_constcast(bool, GET_FIELD(param, "attributes.unique"))) {
112  if((unique_lop[0] == ')') && (key_lop[0] == '&')) {
113  unique_lop = ")||";
114  }
115  amxc_string_prependf(str_expr, "%s==\"%s\"%s", name, value, unique_lop);
116  unique_lop = "||";
117  } else {
118  if((key_lop[0] == '(') && (unique_lop[0] == '|')) {
119  key_lop = "||(";
120  }
121  amxc_string_appendf(str_expr, "%s%s==\"%s\"", key_lop, name, value);
122  key_lop = "&&";
123  }
124  free(value);
125  }
126 
127  if(unique_lop[0] == '|') {
128  amxc_string_prependf(str_expr, "(");
129  }
130  if(key_lop[0] == '&') {
131  amxc_string_appendf(str_expr, ")");
132  }
134 
135 exit:
136  return status;
137 }
138 
139 amxd_status_t PRIVATE amxd_object_build_key_expr(amxc_var_t* const templ_params,
140  amxp_expr_t** expr,
141  const amxc_htable_t* const data) {
143  amxp_expr_status_t expr_status = amxp_expr_status_ok;
144  amxc_string_t str_expr;
145 
146  amxc_string_init(&str_expr, 64);
147 
148  when_null(templ_params, exit);
149  when_null(expr, exit);
150 
151  status = amxd_build_key_expr_string(templ_params, data, &str_expr);
152 
153  if((status == amxd_status_ok) &&
154  !amxc_string_is_empty(&str_expr)) {
155  expr_status = amxp_expr_new(expr, amxc_string_get(&str_expr, 0));
156  when_true_status(expr_status != amxp_expr_status_ok,
157  exit,
159  }
160 
161 exit:
162  amxc_string_clean(&str_expr);
163  return status;
164 }
165 
166 amxp_expr_status_t amxd_object_expr_get_field(UNUSED amxp_expr_t* expr,
167  amxc_var_t* value,
168  const char* path,
169  void* priv) {
170  amxp_expr_status_t status = amxp_expr_status_unknown_error;
171  amxd_object_t* object = (amxd_object_t*) priv;
172  amxd_path_t object_path;
173  const char* op = NULL;
174  const char* param = NULL;
175 
176  when_failed_status(amxd_path_init(&object_path, path),
177  exit,
178  status = amxp_expr_status_field_not_found);
179 
180  op = amxd_path_get(&object_path, AMXD_OBJECT_TERMINATE);
181  param = amxd_path_get_param(&object_path);
182 
183  if(op != NULL) {
184  if(op[0] == '.') {
185  object = amxd_object_findf(object, "%s", op + 1);
186  } else {
187  object = amxd_object_findf(object, "%s", op);
188  }
189  when_null_status(object,
190  exit,
191  status = amxp_expr_status_field_not_found);
192  }
193 
194  if(amxd_object_get_param(object, param, value) == amxd_status_ok) {
195  status = amxp_expr_status_ok;
196  } else {
197  status = amxp_expr_status_field_not_found;
198  }
199 
200 exit:
201  amxd_path_clean(&object_path);
202  return status;
203 }
204 
206  amxp_expr_t** expr,
207  const amxc_var_t* const data) {
209  const amxc_htable_t* ht_data = NULL;
210  amxc_var_t params;
211 
212  amxc_var_init(&params);
213  when_null(data, exit);
214  when_true(amxc_var_type_of(data) != AMXC_VAR_ID_HTABLE, exit);
215  when_true(amxd_object_get_type(templ) != amxd_object_template, exit);
216 
217  when_failed(amxd_object_describe_key_params(templ, &params, amxd_dm_access_public), exit);
218  ht_data = amxc_var_constcast(amxc_htable_t, data);
219  status = amxd_object_build_key_expr(&params, expr, ht_data);
220 
221 exit:
222  amxc_var_clean(&params);
223  return status;
224 }
225 
227  amxp_expr_t* expr) {
228  amxd_object_t* instance = NULL;
229 
230  when_null(templ, exit);
231  when_true(amxd_object_get_type(templ) != amxd_object_template, exit);
232  when_null(expr, exit);
233 
234  amxd_object_for_each(instance, it, templ) {
235  instance = amxc_container_of(it, amxd_object_t, it);
236  if(amxd_object_matches_expr(instance, expr)) {
237  break;
238  }
239  instance = NULL;
240  }
241 
242 exit:
243  return instance;
244 }
245 
247  amxp_expr_t* expr) {
248  amxd_object_t* inst = NULL;
249  amxc_llist_it_t* it = NULL;
250 
251  when_null(instance, exit);
252  when_true(amxd_object_get_type(instance) != amxd_object_instance, exit);
253  when_null(expr, exit);
254 
255  it = amxc_llist_it_get_next(&instance->it);
256  while(it) {
257  inst = amxc_container_of(it, amxd_object_t, it);
258  if(amxd_object_matches_expr(inst, expr)) {
259  break;
260  }
261  it = amxc_llist_it_get_next(it);
262  inst = NULL;
263  }
264 
265 exit:
266  return inst;
267 }
268 
270  amxp_expr_t* expr) {
271  bool retval = false;
272 
273  retval = (amxd_object_find_instance(templ, expr) != NULL);
274 
275  return retval;
276 }
277 
278 bool amxd_object_has_keys(amxd_object_t* const instance) {
279  bool retval = false;
280  amxc_var_t params;
281  const amxc_htable_t* ht_params = NULL;
282 
283  amxc_var_init(&params);
284 
285  when_null(instance, exit);
286  when_true(amxd_object_get_type(instance) != amxd_object_instance &&
288  exit);
289 
290  when_failed(amxd_object_describe_params(instance, &params, amxd_dm_access_public), exit);
291  ht_params = amxc_var_constcast(amxc_htable_t, &params);
292  amxc_htable_for_each(it, ht_params) {
293  amxc_var_t* param = amxc_var_from_htable_it(it);
294  if(amxc_var_constcast(bool, GET_FIELD(param, "attributes.key"))) {
295  retval = true;
296  break;
297  }
298  }
299 
300 exit:
301  amxc_var_clean(&params);
302  return retval;
303 }
304 
306  amxp_expr_t* expr) {
307  bool retval = false;
308 
309  when_null(object, exit);
310  when_null(expr, exit);
311 
312  retval = amxp_expr_evaluate(expr, amxd_object_expr_get_field, object, NULL);
313 
314 exit:
315  return retval;
316 }
#define when_failed_status(x, l, c)
Definition: amxd_assert.h:65
Ambiorix Data Model API header file.
Ambiorix Data Model API header file.
bool amxd_object_matches_expr(amxd_object_t *const object, amxp_expr_t *expr)
bool amxd_object_has_keys(amxd_object_t *const instance)
amxd_status_t amxd_object_new_key_expr(amxd_object_t *const templ, amxp_expr_t **expr, const amxc_var_t *const data)
static amxd_status_t amxd_build_key_expr_string(amxc_var_t *const templ_params, const amxc_htable_t *const data, amxc_string_t *str_expr)
bool amxd_object_has_matching_instances(const amxd_object_t *const templ, amxp_expr_t *expr)
amxd_status_t PRIVATE amxd_object_build_key_expr(amxc_var_t *const templ_params, amxp_expr_t **expr, const amxc_htable_t *const data)
amxp_expr_status_t amxd_object_expr_get_field(UNUSED amxp_expr_t *expr, amxc_var_t *value, const char *path, void *priv)
amxd_object_t * amxd_object_find_next_instance(const amxd_object_t *const instance, amxp_expr_t *expr)
amxd_object_t * amxd_object_find_instance(const amxd_object_t *const templ, amxp_expr_t *expr)
static char * amxd_key_expr_get_value(const amxc_htable_t *const data, const char *name)
amxd_status_t amxd_object_describe_key_params(amxd_object_t *const object, amxc_var_t *const value, amxd_dm_access_t access)
amxd_status_t amxd_object_describe_params(amxd_object_t *const object, amxc_var_t *const value, amxd_dm_access_t access)
Ambiorix path API header file.
#define GET_FIELD(var, field)
Definition: amxd_priv.h:76
enum _amxd_status amxd_status_t
@ amxd_status_missing_key
Definition: amxd_types.h:94
@ amxd_status_ok
Definition: amxd_types.h:78
@ amxd_status_unknown_error
Definition: amxd_types.h:79
@ amxd_status_invalid_value
Definition: amxd_types.h:88
#define AMXD_OBJECT_TERMINATE
Path format flag - when set the object path is terminated with a dot.
Definition: amxd_object.h:214
@ amxd_dm_access_public
Definition: amxd_types.h:136
@ amxd_object_template
Definition: amxd_types.h:183
@ amxd_object_instance
Definition: amxd_types.h:186
amxd_object_t * amxd_object_findf(amxd_object_t *object, const char *rel_path,...) __attribute__((format(printf
Find an object in the data model tree, starting from an object.
amxd_status_t amxd_object_get_param(amxd_object_t *const object, const char *name, amxc_var_t *const value)
Gets a single parameter value.
static amxd_object_type_t amxd_object_get_type(const amxd_object_t *const object)
Returns the object type.
Definition: amxd_object.h:586
#define amxd_object_for_each(type, it, object)
Helper macro for iterating object content.
Definition: amxd_object.h:113
amxd_status_t amxd_path_init(amxd_path_t *path, const char *object_path)
Initializes an amxd_path_t structure.
Definition: amxd_path.c:328
const char * amxd_path_get_param(amxd_path_t *path)
Gets the parameter name.
Definition: amxd_path.c:497
const char * amxd_path_get(amxd_path_t *path, int flags)
Returns the path stored in the amxd_path_t structure.
Definition: amxd_path.c:470
void amxd_path_clean(amxd_path_t *path)
Cleans an amxd_path_t structure.
Definition: amxd_path.c:351
amxc_llist_it_t it
Definition: amxd_types.h:230
static amxd_status_t status