libamxp  1.4.0
Patterns C Implementation
amxp_slot.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_expression.h>
64 
65 #include <amxp_signal_priv.h>
66 
67 static amxp_slot_t* amxp_slot_find(const amxp_signal_t* const sig,
68  amxp_slot_fn_t fn,
69  amxp_slot_t* start) {
70  amxp_slot_t* slot = start;
71  amxc_llist_it_t* it = slot == NULL ? amxc_llist_get_first(&sig->slots) :
72  amxc_llist_it_get_next(&slot->it);
73 
74  while(it != NULL) {
75  slot = amxc_llist_it_get_data(it, amxp_slot_t, it);
76  if(slot->fn == fn) {
77  goto exit;
78  }
79  it = amxc_llist_it_get_next(&slot->it);
80  }
81 
82  slot = NULL;
83 
84 exit:
85  return slot;
86 }
87 
89  const char* const sig_name) {
90  amxc_htable_it_t* hit = NULL;
91  const amxc_htable_t* signals = amxp_get_signals(sig_mngr);
92  amxp_signal_t* sig = NULL;
93 
94  hit = amxc_htable_get(signals, sig_name);
95  when_null(hit, exit);
96 
97  sig = amxc_htable_it_get_data(hit, amxp_signal_t, hit);
98 
99 exit:
100  return sig;
101 }
102 
104  const char* regexp,
105  const char* expression,
106  void* const priv) {
107  int retval = -1;
108  amxp_slot_t* slot = (amxp_slot_t*) calloc(1, sizeof(amxp_slot_t));
109  when_null(slot, exit);
110  slot->fn = fn;
111  slot->priv = priv;
112  slot->regexp = regexp == NULL ? NULL : strdup(regexp);
113  if(expression != NULL) {
114  when_failed(amxp_expr_new(&slot->expr, expression), exit);
115  }
116  retval = 0;
117 
118 exit:
119  if((retval != 0) && (slot != NULL)) {
120  amxp_expr_delete(&slot->expr);
121  free(slot->regexp);
122  free(slot);
123  slot = NULL;
124  }
125  return slot;
126 }
127 
129  amxp_slot_fn_t fn,
130  const char* expression,
131  void* const priv) {
132  int retval = -1;
133  amxp_slot_t* slot = NULL;
134 
135  slot = amxp_slot_find(sig, fn, NULL);
136  if(slot != NULL) {
137  if((expression == NULL) && (slot->expr == NULL) && (priv == NULL)) {
138  if(slot->deleted) {
139  slot->deleted = false;
140  }
141  retval = 0;
142  goto exit;
143  }
144  }
145 
146  slot = amxp_slot_new(fn, NULL, expression, priv);
147  when_null(slot, exit);
148  amxc_llist_append(&sig->slots, &slot->it);
149 
150  retval = 0;
151 
152 exit:
153  return retval;
154 }
155 
157  amxp_slot_fn_t fn,
158  const char* const regexp_str,
159  const char* expression,
160  void* const priv) {
161  int retval = -1;
162  bool use_reg_exp = false;
163  const amxc_htable_t* signals = amxp_get_signals(sigmngr);
164 
165  if((regexp_str != NULL) && (regexp_str[0] != 0)) {
166  regex_t regexp;
167  retval = regcomp(&regexp, regexp_str, REG_NOSUB | REG_EXTENDED);
168  if(retval != 0) {
169  goto exit;
170  }
171  regfree(&regexp);
172  use_reg_exp = true;
173  }
174 
175  if(use_reg_exp) {
176  amxp_slot_t* slot = amxp_slot_new(fn, regexp_str, expression, priv);
177  if(slot == NULL) {
178  retval = -1;
179  goto exit;
180  }
181  amxc_llist_append(&sigmngr->regexp_slots, &slot->it);
182  retval = 0;
183  } else {
184  amxc_htable_for_each(it, signals) {
185  amxp_signal_t* sig = amxc_htable_it_get_data(it, amxp_signal_t, hit);
186  retval = amxp_slot_connect_impl(sig, fn, expression, priv);
187  when_failed(retval, exit);
188  }
189  }
190 
191 exit:
192  return retval;
193 }
194 
195 static int amxp_slot_connnect_all_sigmngrs(const amxc_llist_t* const sigmngrs,
196  amxp_slot_fn_t fn,
197  const char* const regexp,
198  const char* expression,
199  void* const priv) {
200  int retval = -1;
201 
202  amxc_llist_for_each(it, sigmngrs) {
203  amxp_signal_mngr_t* sigmngr = amxc_llist_it_get_data(it,
205  it);
207  fn,
208  regexp,
209  expression,
210  priv), exit);
211  }
212 
213  retval = 0;
214 
215 exit:
216  return retval;
217 }
218 
220  amxp_slot_t* slot,
221  amxp_slot_fn_t fn) {
222  while(slot != NULL) {
223  slot->deleted = true;
224  slot = amxp_slot_find(sig, fn, slot);
225  }
226 }
227 
229  amxp_slot_fn_t fn) {
230  const amxc_htable_t* signals = amxp_get_signals(sigmngr);
231  amxc_llist_it_t* next = NULL;
232  amxc_llist_it_t* regexp_it = NULL;
233  amxc_htable_for_each(it, signals) {
234  amxp_slot_t* slot = NULL;
235  amxp_signal_t* sig = NULL;
236  sig = amxc_htable_it_get_data(it, amxp_signal_t, hit);
237  slot = amxp_slot_find(sig, fn, NULL);
238  amxp_slot_delete_all(sig, slot, fn);
239  }
240 
241  regexp_it = amxc_llist_get_first(&sigmngr->regexp_slots);
242  while(regexp_it) {
243  amxp_slot_t* slot = NULL;
244  next = amxc_llist_it_get_next(regexp_it);
245  slot = amxc_llist_it_get_data(regexp_it, amxp_slot_t, it);
246  if(slot->fn == fn) {
247  slot->deleted = true;
248  }
249  regexp_it = next;
250  }
251 }
252 
253 static void amxp_slot_disconnect_all_sgmngrs(const amxc_llist_t* const sigmngrs,
254  amxp_slot_fn_t fn) {
255 
256  amxc_llist_for_each(it, sigmngrs) {
257  amxp_signal_mngr_t* sigmngr = amxc_llist_it_get_data(it,
259  it);
261  }
262 }
263 
265  const char* const sig_name,
266  amxp_slot_fn_t fn) {
267  int retval = -1;
268  amxp_signal_t* sig = NULL;
269  amxp_slot_t* slot = NULL;
270  sig_mngr = amxp_get_sigmngr(sig_mngr);
271 
272  sig = amxp_slot_find_signal(sig_mngr, sig_name);
273  if(sig != NULL) {
274  slot = amxp_slot_find(sig, fn, NULL);
275  }
276  if((sig != NULL) && (slot != NULL)) {
277  amxp_slot_delete_all(sig, slot, fn);
278  retval = 0;
279  } else {
280  amxc_llist_it_t* it = amxc_llist_get_first(&sig_mngr->regexp_slots);
281  amxc_llist_it_t* next = NULL;
282  while(it) {
283  regex_t regexp;
284  slot = amxc_llist_it_get_data(it, amxp_slot_t, it);
285  next = amxc_llist_it_get_next(it);
286  regcomp(&regexp, slot->regexp, REG_NOSUB | REG_EXTENDED);
287  if((slot->fn == fn) &&
288  ( regexec(&regexp, sig_name, 0, NULL, 0) == 0)) {
289  slot->deleted = true;
290  retval = 0;
291  }
292  regfree(&regexp);
293  it = next;
294  }
295  }
296 
297  return retval;
298 }
299 
301  const char* const sig_name,
302  const char* const expression,
303  amxp_slot_fn_t fn,
304  void* const priv) {
305  int retval = -1;
306  amxp_signal_t* sig = NULL;
307 
308  when_null(sig_name, exit);
309  when_true(*sig_name == 0, exit);
310  when_null(fn, exit);
311 
312  if(strcmp(sig_name, "*") == 0) {
313  if(sig_mngr == NULL) {
314  retval = amxp_slot_connect_all(NULL, expression, fn, priv);
315  } else {
316  retval = amxp_slot_connnect_all_of(sig_mngr, fn, NULL, expression, priv);
317  }
318  goto exit;
319  }
320 
321  sig = amxp_slot_find_signal(sig_mngr, sig_name);
322  when_null(sig, exit);
323 
324  retval = amxp_slot_connect_impl(sig, fn, expression, priv);
325 
326 exit:
327  return retval;
328 }
329 
331  const char* const sig_reg_exp,
332  const char* const expression,
333  amxp_slot_fn_t fn,
334  void* const priv) {
335  int retval = -1;
336  amxp_signal_mngr_t* mngr = NULL;
337  when_null(sig_reg_exp, exit);
338  when_true(*sig_reg_exp == 0, exit);
339  when_null(fn, exit);
340 
341  mngr = amxp_get_sigmngr(sig_mngr);
342  when_null(mngr, exit);
343  retval = amxp_slot_connnect_all_of(mngr,
344  fn,
345  sig_reg_exp,
346  expression,
347  priv);
348 
349 exit:
350  return retval;
351 }
352 
353 int amxp_slot_connect_all(const char* sig_reg_exp,
354  const char* const expression,
355  amxp_slot_fn_t fn,
356  void* const priv) {
357  int retval = -1;
358  amxc_llist_t* sigmngrs = NULL;
359  amxc_llist_t* pending_sigmngrs = NULL;
360 
361  when_null(fn, exit);
362 
363  amxp_get_sigmngrs(&sigmngrs, &pending_sigmngrs);
364  when_failed(amxp_slot_connnect_all_sigmngrs(sigmngrs,
365  fn,
366  sig_reg_exp,
367  expression,
368  priv), exit);
369  when_failed(amxp_slot_connnect_all_sigmngrs(pending_sigmngrs,
370  fn,
371  sig_reg_exp,
372  expression,
373  priv), exit);
374  retval = 0;
375 
376 exit:
377  return retval;
378 }
379 
381  const char* const sig_name,
382  amxp_slot_fn_t fn) {
383  int retval = -1;
384 
385  when_null(sig_name, exit);
386  when_true(*sig_name == 0, exit);
387  when_null(fn, exit);
388 
389  if(strcmp(sig_name, "*") == 0) {
390  if(sig_mngr == NULL) {
392  } else {
393  amxp_slot_disconnnect_all_of(sig_mngr, fn);
394  }
395  retval = 0;
396  goto exit;
397  }
398 
399  retval = amxp_slot_disconnect_name(sig_mngr, sig_name, fn);
400 
401 exit:
402  return retval;
403 }
404 
406  amxp_slot_fn_t fn,
407  void* priv) {
408  return amxp_slot_disconnect_signal_with_priv(sig_mngr, NULL, fn, priv);
409 }
410 
412  const char* sig_name,
413  amxp_slot_fn_t fn,
414  void* priv) {
415  int retval = -1;
416  amxc_llist_it_t* slot_it = NULL;
417  amxc_llist_it_t* next = NULL;
418  const amxc_htable_t* signals = NULL;
419  sig_mngr = amxp_get_sigmngr(sig_mngr);
420  signals = amxp_get_signals(sig_mngr);
421 
422  amxc_htable_for_each(it, signals) {
423  amxp_signal_t* sig = amxc_htable_it_get_data(it, amxp_signal_t, hit);
424  if((sig_name != NULL) && (strcmp(sig_name, sig->name) != 0)) {
425  continue;
426  }
427  slot_it = amxc_llist_get_first(&sig->slots);
428  while(slot_it != NULL) {
429  amxp_slot_t* slot = NULL;
430  next = amxc_llist_it_get_next(slot_it);
431  slot = amxc_llist_it_get_data(slot_it, amxp_slot_t, it);
432  if(((slot->fn == fn) || (fn == NULL)) &&
433  ( slot->priv == priv)) {
434  slot->deleted = true;
435  }
436  slot_it = next;
437  }
438  }
439 
440  if(sig_name == NULL) {
441  slot_it = amxc_llist_get_first(&sig_mngr->regexp_slots);
442  while(slot_it != NULL) {
443  amxp_slot_t* slot = NULL;
444  next = amxc_llist_it_get_next(slot_it);
445  slot = amxc_llist_it_get_data(slot_it, amxp_slot_t, it);
446  if(((slot->fn == fn) || (fn == NULL)) &&
447  ( slot->priv == priv)) {
448  amxc_llist_it_clean(slot_it, amxp_free_slots);
449  }
450  slot_it = next;
451  }
452  }
453 
454  retval = 0;
455 
456  return retval;
457 }
458 
460  amxc_llist_t* sigmngrs = NULL;
461  amxc_llist_t* pending_sigmngrs = NULL;
462 
463  when_null(fn, exit);
464 
465  amxp_get_sigmngrs(&sigmngrs, &pending_sigmngrs);
466  amxp_slot_disconnect_all_sgmngrs(sigmngrs, fn);
467  amxp_slot_disconnect_all_sgmngrs(pending_sigmngrs, fn);
468 
469 exit:
470  return;
471 }
Ambiorix expression parser and evaluate API header file.
amxp_signal_mngr_t * amxp_get_sigmngr(amxp_signal_mngr_t *sig_mngr)
Definition: amxp_signal.c:315
const amxc_htable_t PRIVATE * amxp_get_signals(const amxp_signal_mngr_t *sig_mngr)
Definition: amxp_signal.c:325
void PRIVATE amxp_get_sigmngrs(amxc_llist_t **sigmngrs, amxc_llist_t **pending_sigmngrs)
Definition: amxp_signal.c:319
void PRIVATE amxp_free_slots(amxc_llist_it_t *it)
Definition: amxp_signal.c:99
static void amxp_slot_disconnect_all_sgmngrs(const amxc_llist_t *const sigmngrs, amxp_slot_fn_t fn)
Definition: amxp_slot.c:253
static void amxp_slot_disconnnect_all_of(const amxp_signal_mngr_t *const sigmngr, amxp_slot_fn_t fn)
Definition: amxp_slot.c:228
static int amxp_slot_connnect_all_sigmngrs(const amxc_llist_t *const sigmngrs, amxp_slot_fn_t fn, const char *const regexp, const char *expression, void *const priv)
Definition: amxp_slot.c:195
static int amxp_slot_disconnect_name(amxp_signal_mngr_t *sig_mngr, const char *const sig_name, amxp_slot_fn_t fn)
Definition: amxp_slot.c:264
static amxp_slot_t * amxp_slot_new(amxp_slot_fn_t fn, const char *regexp, const char *expression, void *const priv)
Definition: amxp_slot.c:103
static int amxp_slot_connect_impl(amxp_signal_t *sig, amxp_slot_fn_t fn, const char *expression, void *const priv)
Definition: amxp_slot.c:128
static void amxp_slot_delete_all(amxp_signal_t *sig, amxp_slot_t *slot, amxp_slot_fn_t fn)
Definition: amxp_slot.c:219
static amxp_slot_t * amxp_slot_find(const amxp_signal_t *const sig, amxp_slot_fn_t fn, amxp_slot_t *start)
Definition: amxp_slot.c:67
static int amxp_slot_connnect_all_of(amxp_signal_mngr_t *const sigmngr, amxp_slot_fn_t fn, const char *const regexp_str, const char *expression, void *const priv)
Definition: amxp_slot.c:156
static amxp_signal_t * amxp_slot_find_signal(const amxp_signal_mngr_t *const sig_mngr, const char *const sig_name)
Definition: amxp_slot.c:88
amxp_expr_status_t amxp_expr_new(amxp_expr_t **expr, const char *expression)
Allocates and initializes an expression.
void amxp_expr_delete(amxp_expr_t **expr)
Deletes a previously allocated expression structure.
void amxp_slot_disconnect_all(amxp_slot_fn_t fn)
Disconnects a slot from all signals it was connected to.
Definition: amxp_slot.c:459
int amxp_slot_connect_all(const char *sig_reg_exp, const char *const expression, amxp_slot_fn_t fn, void *const priv)
Connects a slot to all existing and future signals.
Definition: amxp_slot.c:353
int amxp_slot_disconnect_signal_with_priv(amxp_signal_mngr_t *sig_mngr, const char *sig_name, amxp_slot_fn_t fn, void *priv)
Disconnects a slot from a signal.
Definition: amxp_slot.c:411
int amxp_slot_connect_filtered(amxp_signal_mngr_t *const sig_mngr, const char *const sig_reg_exp, const char *const expression, amxp_slot_fn_t fn, void *const priv)
Connects a slot (function) to signals using a regular expression.
Definition: amxp_slot.c:330
int amxp_slot_disconnect(amxp_signal_mngr_t *const sig_mngr, const char *const sig_name, amxp_slot_fn_t fn)
Disconnects a slot from (a) signal(s).
Definition: amxp_slot.c:380
void(* amxp_slot_fn_t)(const char *const sig_name, const amxc_var_t *const data, void *const priv)
Slot callback function signature.
Definition: amxp_slot.h:93
int amxp_slot_connect(amxp_signal_mngr_t *const sig_mngr, const char *const sig_name, const char *const expression, amxp_slot_fn_t fn, void *const priv)
Connects a slot (function) to a named signal of a signal manager.
Definition: amxp_slot.c:300
int amxp_slot_disconnect_with_priv(amxp_signal_mngr_t *sig_mngr, amxp_slot_fn_t fn, void *priv)
Disconnects a slot from (a) signal(s).
Definition: amxp_slot.c:405
Structure containing the signal manager information.
Definition: amxp_signal.h:103
amxc_llist_t regexp_slots
Definition: amxp_signal.h:106
Structure containing the signal information.
Definition: amxp_signal.h:119
amxc_llist_t slots
Definition: amxp_signal.h:121
const char * name
Definition: amxp_signal.h:122
amxp_slot_fn_t fn
amxc_llist_it_t it
amxp_expr_t * expr
static amxp_signal_mngr_t * sigmngr