libamxd  6.4.1
Data Model Manager
amxd_object_search_priv.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 <stdio.h>
61 #include <string.h>
62 #include <ctype.h>
63 
64 #include <amxc/amxc.h>
65 #include <amxp/amxp.h>
66 
67 #include <amxd/amxd_types.h>
68 #include <amxd/amxd_object.h>
70 #include <amxd/amxd_dm.h>
71 #include <amxd/amxd_dm_functions.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 
79  bool* key_path,
80  amxc_llist_t* paths,
81  amxc_llist_it_t* part);
82 
83 static
85  bool* key_path,
86  const char* const path,
88  amxd_object_t* result = NULL;
89  size_t length = strlen(path);
90  int64_t index = 0;
91  int offset = 0;
92  char* endptr = NULL;
93 
94  if(path[length - 1] == '.') {
95  length--;
96  }
97  if(path[0] == '[') {
98  offset = 1;
99  length -= 2;
100  }
101 
102  when_true_status(length == 0,
103  exit,
105 
106  index = strtoll(path + offset, &endptr, 0);
107 
108  if((endptr != path) && ((*endptr == '.') || (*endptr == '\0') || (*endptr == ']'))) {
109  result = amxd_object_get_instance(object, NULL, index);
110  } else {
111  char* copy_path = strdup(path + offset);
112  copy_path[length] = 0;
113  result = amxd_object_get_instance(object, copy_path, 0);
114  if(result != NULL) {
115  *key_path = true;
116  }
117  free(copy_path);
118  }
119  if(result == NULL) {
121  }
122 
123 exit:
124  return result;
125 }
126 
127 static
129  bool* key_path,
130  const char* path,
132  amxd_object_t* result = object;
133  amxd_object_t* child = NULL;
134  size_t length = strlen(path);
135  when_true(length == 0, exit);
136 
137  child = amxd_object_get_child(result, path);
138  if(child != NULL) {
139  result = child;
140  } else {
141  result = amxd_template_find(object, key_path, path, status);
142  }
143 
144 exit:
145  if(result == NULL) {
147  }
148  return result;
149 }
150 
151 static
153  bool* key_path,
154  char* str_part,
156  amxd_object_t* result = NULL;
157  amxd_object_t* tmp = NULL;
158  amxp_expr_t expr;
159  int length = 0;
160  int offset = 0;
161 
162  length = strlen(str_part);
163  tmp = amxd_template_find(templ, key_path, str_part, status);
164  if(tmp != NULL) {
165  result = tmp;
166  goto exit;
167  }
168 
169  when_true(*status != amxd_status_object_not_found, exit);
170 
171  if(str_part[0] == '[') {
172  length = strlen(str_part);
173  offset = 1;
174  str_part[length - 1] = 0;
175  }
176 
177  if(amxp_expr_init(&expr, str_part + offset) != 0) {
179  goto exit;
180  }
181 
182  result = amxd_object_find_instance(templ, &expr);
183  if(result == NULL) {
184  if(expr.status != amxp_expr_status_ok) {
186  } else {
188  }
189  amxp_expr_clean(&expr);
190  goto exit;
191  }
192 
193  tmp = amxd_object_find_next_instance(result, &expr);
194  if(tmp != NULL) {
196  result = NULL;
197  }
198 
199  amxp_expr_clean(&expr);
200 
201 exit:
202  if(str_part[0] == '[') {
203  str_part[length - 1] = ']';
204  }
205 
206  return result;
207 }
208 
209 static
211  bool* key_path,
212  amxc_llist_t* paths,
213  amxc_llist_it_t* next) {
215  if(next == NULL) {
216  amxc_string_t* obj_path = NULL;
218  if(path == NULL) {
220  goto exit;
221  }
222  amxc_string_new(&obj_path, 0);
223  amxc_string_push_buffer(obj_path, path, strlen(path) + 1);
224  amxc_llist_append(paths, &obj_path->it);
225  } else {
226  status = amxd_object_resolve_next(object, key_path, paths, next);
227  }
228 
229 exit:
230  return status;
231 }
232 
233 static
235  bool* key_path,
236  amxc_llist_t* paths,
237  amxc_llist_it_t* part) {
239  uint32_t count = 0;
240  amxd_object_for_each(instance, it, object) {
241  amxd_object_t* instance = amxc_container_of(it, amxd_object_t, it);
242  status = amxd_resolve_add_path_or_continue(instance, key_path, paths, part->next);
243  if(status == amxd_status_ok) {
244  count++;
245  }
246  }
247 
248  status = (count > 0 || amxc_llist_is_empty(&object->instances)) ?
250 
251  return status;
252 }
253 
254 static
256  bool* key_path,
257  amxc_llist_t* paths,
258  amxc_llist_it_t* part) {
260  amxc_var_t* var_part = amxc_var_from_llist_it(part);
261  char* txt_part = amxc_var_dyncast(cstring_t, var_part);
262  amxd_object_t* tmp = NULL;
263  amxp_expr_t expr;
264  int length = strlen(txt_part);
265 
266  tmp = amxd_template_find(object, key_path, txt_part, &status);
267  if(tmp != NULL) {
268  status = amxd_resolve_add_path_or_continue(tmp, key_path, paths, part->next);
269  goto exit;
270  }
271 
273  goto exit;
274  }
275 
276  txt_part[length - 1] = 0;
277  if(amxp_expr_init(&expr, txt_part + 1) != 0) {
279  goto exit;
280  }
281 
283  object = amxd_object_find_instance(object, &expr);
284 
285  while(object != NULL) {
286  status = amxd_resolve_add_path_or_continue(object, key_path, paths, part->next);
287  when_failed_status(status, exit, amxp_expr_clean(&expr));
288  object = amxd_object_find_next_instance(object, &expr);
289  }
290 
291  amxp_expr_clean(&expr);
292 
293 exit:
294  free(txt_part);
295  return status;
296 }
297 
298 static
300  bool* key_path,
301  amxc_llist_t* paths,
302  amxc_llist_it_t* part) {
304  amxc_var_t* var_part = amxc_var_from_llist_it(part);
305  const char* str_part = amxc_var_constcast(cstring_t, var_part);
306 
307  if(str_part[0] == '*') {
308  status = amxd_template_add_all_instances(object, key_path, paths, part);
309  } else {
310  status = amxd_template_add_matching_instances(object, key_path, paths, part);
311  }
312 
313  return status;
314 }
315 
316 static
318  bool* key_path,
319  amxc_llist_t* paths,
320  amxc_llist_it_t* part) {
322  amxd_object_t* result = object;
323  amxc_var_t* var_part = NULL;
324  const char* str_part = NULL;
325 
326  var_part = amxc_var_from_llist_it(part);
327  str_part = amxc_var_constcast(cstring_t, var_part);
328 
329  switch(str_part[0]) {
330  case '[':
331  case '*':
334  goto exit;
335  }
336  status = amxd_object_resolve_instances(object, key_path, paths, part);
337  break;
338  case '.':
339  status = amxd_resolve_add_path_or_continue(result, key_path, paths, part->next);
340  break;
341  case '^':
342  result = amxd_object_get_parent(result);
343  status = amxd_resolve_add_path_or_continue(result, key_path, paths, part->next);
344  break;
345  default:
347  result = amxd_object_find(result, key_path, str_part, &status);
348  if(result == NULL) {
350  }
351  } else {
352  result = amxd_object_find(result, key_path, str_part, &status);
353  }
354  if(result != NULL) {
355  status = amxd_resolve_add_path_or_continue(result, key_path, paths, part->next);
356  }
357  break;
358  }
359 
360 exit:
361  return status;
362 }
363 
365  bool* key_path,
366  amxd_path_t* path,
368  amxd_object_t* result = object;
369  char* str_part = NULL;
370 
371  amxc_var_for_each(var, (&path->parts)) {
372  str_part = amxc_var_take(cstring_t, var);
373  switch(str_part[0]) {
374  case '*':
376  result = NULL;
377  break;
378  case '{':
381  result = NULL;
382  }
383  break;
384  case '[':
387  result = NULL;
388  } else {
389  result = amxd_template_find_instance(result, key_path, str_part, status);
390  }
391  break;
392  case '.':
393  break;
394  case '^':
395  result = amxd_object_get_parent(result);
396  break;
397  default:
398  result = amxd_object_find(result, key_path, str_part, status);
399  break;
400  }
401  amxc_var_push(cstring_t, var, str_part);
402 
403  when_null(result, exit);
404  }
405 
406 exit:
407  return result;
408 }
409 
411  bool* key_path,
412  amxc_llist_t* paths,
413  amxd_path_t* path) {
415  amxc_llist_it_t* path_part_it = NULL;
416  const amxc_llist_t* lparts = NULL;
417 
418  lparts = amxc_var_constcast(amxc_llist_t, &path->parts);
419  path_part_it = amxc_llist_get_first(lparts);
420  if(path_part_it != NULL) {
421  status = amxd_object_resolve_next(object, key_path, paths, path_part_it);
422  } else {
423  status = amxd_resolve_add_path_or_continue(object, key_path, paths, NULL);
424  }
425  when_failed(status, exit);
426 
427 exit:
428  if(status != amxd_status_ok) {
429  amxc_llist_clean(paths, amxc_string_list_it_free);
430  }
431  return status;
432 }
#define when_failed_status(x, l, c)
Definition: amxd_assert.h:65
Ambiorix Data Model API header file.
Ambiorix Data Model API header file.
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 amxd_object_t * amxd_template_find(amxd_object_t *const object, bool *key_path, const char *const path, amxd_status_t *status)
static amxd_status_t amxd_template_add_all_instances(amxd_object_t *object, bool *key_path, amxc_llist_t *paths, amxc_llist_it_t *part)
static amxd_object_t * amxd_template_find_instance(amxd_object_t *templ, bool *key_path, char *str_part, amxd_status_t *status)
static amxd_status_t amxd_object_resolve_instances(amxd_object_t *const object, bool *key_path, amxc_llist_t *paths, amxc_llist_it_t *part)
static amxd_status_t amxd_object_resolve_next(amxd_object_t *const object, bool *key_path, amxc_llist_t *paths, amxc_llist_it_t *part)
static amxd_status_t amxd_template_add_matching_instances(amxd_object_t *object, bool *key_path, amxc_llist_t *paths, amxc_llist_it_t *part)
static amxd_status_t amxd_resolve_add_path_or_continue(amxd_object_t *object, bool *key_path, amxc_llist_t *paths, amxc_llist_it_t *next)
amxd_status_t amxd_object_resolve_internal(amxd_object_t *const object, bool *key_path, amxc_llist_t *paths, amxd_path_t *path)
static amxd_object_t * amxd_object_find(amxd_object_t *const object, bool *key_path, const char *path, amxd_status_t *status)
amxd_object_t * amxd_object_find_internal(amxd_object_t *const object, bool *key_path, amxd_path_t *path, amxd_status_t *status)
enum _amxd_status amxd_status_t
@ amxd_status_invalid_path
Definition: amxd_types.h:99
@ amxd_status_object_not_found
Definition: amxd_types.h:80
@ amxd_status_ok
Definition: amxd_types.h:78
@ amxd_status_duplicate
Definition: amxd_types.h:91
#define AMXD_OBJECT_INDEXED
Name and path format flag - use index for instance objects.
Definition: amxd_object.h:176
#define AMXD_OBJECT_TERMINATE
Path format flag - when set the object path is terminated with a dot.
Definition: amxd_object.h:214
@ amxd_object_template
Definition: amxd_types.h:183
amxd_object_t amxd_status_t amxd_status_t char * amxd_object_get_path(const amxd_object_t *object, const uint32_t flags)
Get the full path of the object.
amxd_object_t * amxd_object_get_parent(const amxd_object_t *const object)
Get the parent object.
amxd_object_t * amxd_object_get_child(const amxd_object_t *object, const char *name)
Get a child of the object.
amxd_object_t * amxd_object_get_instance(const amxd_object_t *object, const char *name, uint32_t index)
Get an instance of the template 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
#define amxd_object_for_each(type, it, object)
Helper macro for iterating object content.
Definition: amxd_object.h:113
amxc_llist_t instances
Definition: amxd_types.h:244
amxc_var_t parts
Definition: amxd_types.h:409
static amxd_status_t status