From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../third_party/nrappkit/src/registry/registrycb.c | 440 +++++++++++++++++++++ 1 file changed, 440 insertions(+) create mode 100644 dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c (limited to 'dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c') diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c new file mode 100644 index 0000000000..4b326a1ee2 --- /dev/null +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c @@ -0,0 +1,440 @@ +/* + * + * registrycb.c + * + * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registrycb.c,v $ + * $Revision: 1.3 $ + * $Date: 2007/06/26 22:37:51 $ + * + * Callback-related functions + * + * + * Copyright (C) 2005, Network Resonance, Inc. + * Copyright (C) 2006, Network Resonance, Inc. + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Network Resonance, Inc. nor the name of any + * contributors to this software may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +#include +#include +#include "registry.h" +#include "registry_int.h" +#include "r_assoc.h" +#include "r_errors.h" +#include "nr_common.h" +#include "r_log.h" +#include "r_macros.h" + +static char CB_ACTIONS[] = { NR_REG_CB_ACTION_ADD, + NR_REG_CB_ACTION_DELETE, + NR_REG_CB_ACTION_CHANGE, + NR_REG_CB_ACTION_FINAL }; + +typedef struct nr_reg_cb_info_ { + char action; + void (*cb)(void *cb_arg, char action, NR_registry name); + void *cb_arg; + NR_registry name; +} nr_reg_cb_info; + +/* callbacks that are registered, a mapping from names like "foo.bar.baz" + * to an r_assoc which contains possibly several nr_reg_cb_info*'s */ +static r_assoc *nr_registry_callbacks = 0; + +//static size_t SIZEOF_CB_ID = (sizeof(void (*)()) + 1); +#define SIZEOF_CB_ID (sizeof(void (*)()) + 1) + +static int nr_reg_validate_action(char action); +static int nr_reg_assoc_destroy(void *ptr); +static int compute_cb_id(void *cb, char action, unsigned char cb_id[SIZEOF_CB_ID]); +static int nr_reg_info_free(void *ptr); +static int nr_reg_raise_event_recurse(char *name, char *tmp, int action); +static int nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg); +static int nr_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name)); + +int +nr_reg_cb_init() +{ + int r, _status; + + if (nr_registry_callbacks == 0) { + if ((r=r_assoc_create(&nr_registry_callbacks, r_assoc_crc32_hash_compute, 12))) + ABORT(r); + } + + _status=0; + abort: + if (_status) { + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't init notifications: %s", nr_strerror(_status)); + } + return(_status); +} + +int +nr_reg_validate_action(char action) +{ + int _status; + size_t i; + + for (i = 0; i < sizeof(CB_ACTIONS); ++i) { + if (action == CB_ACTIONS[i]) + return 0; + } + ABORT(R_BAD_ARGS); + + _status=0; + abort: + return(_status); +} + +int +nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg) +{ + int r, _status; + r_assoc *assoc; + int create_assoc = 0; + nr_reg_cb_info *info; + int create_info = 0; + unsigned char cb_id[SIZEOF_CB_ID]; + + if (name == 0 || cb == 0) + ABORT(R_BAD_ARGS); + + if (nr_registry_callbacks == 0) + ABORT(R_FAILED); + + if ((r=nr_reg_is_valid(name))) + ABORT(r); + + if ((r=nr_reg_validate_action(action))) + ABORT(r); + + if ((r=r_assoc_fetch(nr_registry_callbacks, name, strlen(name)+1, (void*)&assoc))) { + if (r == R_NOT_FOUND) + create_assoc = 1; + else + ABORT(r); + } + + if (create_assoc) { + if ((r=r_assoc_create(&assoc, r_assoc_crc32_hash_compute, 5))) + ABORT(r); + + if ((r=r_assoc_insert(nr_registry_callbacks, name, strlen(name)+1, assoc, 0, nr_reg_assoc_destroy, R_ASSOC_NEW))) + ABORT(r); + } + + if ((r=compute_cb_id(cb, action, cb_id))) + ABORT(r); + + if ((r=r_assoc_fetch(assoc, (char*)cb_id, SIZEOF_CB_ID, (void*)&info))) { + if (r == R_NOT_FOUND) + create_info = 1; + else + ABORT(r); + } + + if (create_info) { + if (!(info=(void*)RCALLOC(sizeof(*info)))) + ABORT(R_NO_MEMORY); + } + + strncpy(info->name, name, sizeof(info->name)); + info->action = action; + info->cb = cb; + info->cb_arg = cb_arg; + + if (create_info) { + if ((r=r_assoc_insert(assoc, (char*)cb_id, SIZEOF_CB_ID, info, 0, nr_reg_info_free, R_ASSOC_NEW))) + ABORT(r); + } + + _status=0; + abort: + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "register callback %p on '%s' for '%s' %s", cb, name, nr_reg_action_name(action), (_status ? "FAILED" : "succeeded")); + + if (_status) { + if (create_info && info) RFREE(info); + if (create_assoc && assoc) nr_reg_assoc_destroy(&assoc); + } + return(_status); +} + +int +nr_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name)) +{ + int r, _status; + r_assoc *assoc; + int size; + unsigned char cb_id[SIZEOF_CB_ID]; + + if (name == 0 || cb == 0) + ABORT(R_BAD_ARGS); + + if (nr_registry_callbacks == 0) + ABORT(R_FAILED); + + if ((r=nr_reg_is_valid(name))) + ABORT(r); + + if ((r=nr_reg_validate_action(action))) + ABORT(r); + + if ((r=r_assoc_fetch(nr_registry_callbacks, name, strlen(name)+1, (void*)&assoc))) { + if (r != R_NOT_FOUND) + ABORT(r); + } + else { + if ((r=compute_cb_id(cb, action, cb_id))) + ABORT(r); + + if ((r=r_assoc_delete(assoc, (char*)cb_id, SIZEOF_CB_ID))) { + if (r != R_NOT_FOUND) + ABORT(r); + } + + if ((r=r_assoc_num_elements(assoc, &size))) + ABORT(r); + + if (size == 0) { + if ((r=r_assoc_delete(nr_registry_callbacks, name, strlen(name)+1))) + ABORT(r); + } + } + + _status=0; + abort: + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "unregister callback %p on '%s' for '%s' %s", cb, name, nr_reg_action_name(action), (_status ? "FAILED" : "succeeded")); + + return(_status); +} + +int +compute_cb_id(void *cb, char action, unsigned char cb_id[SIZEOF_CB_ID]) +{ + /* callbacks are identified by the pointer to the cb function plus + * the action being watched */ + assert(sizeof(cb) == sizeof(void (*)())); + assert(sizeof(cb) == (SIZEOF_CB_ID - 1)); + + memcpy(cb_id, &(cb), sizeof(cb)); + cb_id[SIZEOF_CB_ID-1] = action; + + return 0; +} + +char * +nr_reg_action_name(int action) +{ + char *name = "*Unknown*"; + + switch (action) { + case NR_REG_CB_ACTION_ADD: name = "add"; break; + case NR_REG_CB_ACTION_DELETE: name = "delete"; break; + case NR_REG_CB_ACTION_CHANGE: name = "change"; break; + case NR_REG_CB_ACTION_FINAL: name = "final"; break; + } + + return name; +} + +int +nr_reg_assoc_destroy(void *ptr) +{ + return r_assoc_destroy((r_assoc**)&ptr); +} + +int +nr_reg_info_free(void *ptr) +{ + RFREE(ptr); + return 0; +} + +/* call with tmp=0 */ +int +nr_reg_raise_event_recurse(char *name, char *tmp, int action) +{ + int r, _status; + r_assoc *assoc; + nr_reg_cb_info *info; + r_assoc_iterator iter; + char *key; + int keyl; + char *c; + int free_tmp = 0; + int count; + + if (tmp == 0) { + if (!(tmp = (char*)r_strdup(name))) + ABORT(R_NO_MEMORY); + free_tmp = 1; + } + + if ((r=r_assoc_fetch(nr_registry_callbacks, tmp, strlen(tmp)+1, (void*)&assoc))) { + if (r != R_NOT_FOUND) + ABORT(r); + + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "No callbacks found on '%s'", tmp); + } + else { + if (!r_assoc_num_elements(assoc, &count)) { + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "%d callback%s found on '%s'", + count, ((count == 1) ? "" : "s"), tmp); + } + + if ((r=r_assoc_init_iter(assoc, &iter))) + ABORT(r); + + for (;;) { + if ((r=r_assoc_iter(&iter, (void*)&key, &keyl, (void*)&info))) { + if (r == R_EOD) + break; + else + ABORT(r); + } + + if (info->action == action) { + r_log(NR_LOG_REGISTRY, LOG_DEBUG, + "Invoking callback %p for '%s'", + info->cb, + nr_reg_action_name(info->action)); + + (void)info->cb(info->cb_arg, action, name); + } + else { + r_log(NR_LOG_REGISTRY, LOG_DEBUG, + "Skipping callback %p for '%s'", + info->cb, + nr_reg_action_name(info->action)); + } + } + } + + if (strlen(tmp) > 0) { + c = strrchr(tmp, '.'); + if (c != 0) + *c = '\0'; + else + tmp[0] = '\0'; + + if ((r=nr_reg_raise_event_recurse(name, tmp, action))) + ABORT(r); + } + + _status=0; + abort: + if (free_tmp && tmp != 0) RFREE(tmp); + return(_status); +} + + +/* NON-STATIC METHODS */ + +int +nr_reg_raise_event(NR_registry name, int action) +{ + int r, _status; + int count; + char *event = nr_reg_action_name(action); + + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "raising event '%s' on '%s'", event, name); + + if (name == 0) + ABORT(R_BAD_ARGS); + + if ((r=nr_reg_validate_action(action))) + ABORT(r); + + if ((r=r_assoc_num_elements(nr_registry_callbacks, &count))) + ABORT(r); + + if (count > 0) { + if ((r=nr_reg_raise_event_recurse(name, 0, action))) + ABORT(r); + } + else { + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "No callbacks found"); + return 0; + } + + _status=0; + abort: + return(_status); +} + + +/* PUBLIC METHODS */ + +int +NR_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg) +{ + int r, _status; + size_t i; + + for (i = 0; i < sizeof(CB_ACTIONS); ++i) { + if (action & CB_ACTIONS[i]) { + if ((r=nr_reg_register_callback(name, CB_ACTIONS[i], cb, cb_arg))) + ABORT(r); + + action &= ~(CB_ACTIONS[i]); + } + } + + if (action) + ABORT(R_BAD_ARGS); + + _status=0; + abort: + return(_status); +} + +int +NR_reg_unregister_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name)) +{ + int r, _status; + size_t i; + + for (i = 0; i < sizeof(CB_ACTIONS); ++i) { + if (action & CB_ACTIONS[i]) { + if ((r=nr_reg_unregister_callback(name, CB_ACTIONS[i], cb))) + ABORT(r); + + action &= ~(CB_ACTIONS[i]); + } + } + + if (action) + ABORT(R_BAD_ARGS); + + _status=0; + abort: + return(_status); +} -- cgit v1.2.3