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 --- .../nrappkit/src/registry/registry_local.c | 1168 ++++++++++++++++++++ 1 file changed, 1168 insertions(+) create mode 100644 dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_local.c (limited to 'dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_local.c') diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_local.c b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_local.c new file mode 100644 index 0000000000..ed6e19aaa0 --- /dev/null +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_local.c @@ -0,0 +1,1168 @@ +/* + * + * registry.c + * + * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry_local.c,v $ + * $Revision: 1.4 $ + * $Date: 2007/11/21 00:09:13 $ + * + * Datastore for tracking configuration and related info. + * + * + * 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 +#ifndef WIN32 +#include +#include +#include +#endif +#ifdef OPENSSL +#include +#endif +#include +#include "registry.h" +#include "registry_int.h" +#include "registry_vtbl.h" +#include "r_assoc.h" +#include "nr_common.h" +#include "r_log.h" +#include "r_errors.h" +#include "r_macros.h" + +/* if C were an object-oriented language, nr_scalar_registry_node and + * nr_array_registry_node would subclass nr_registry_node, but it isn't + * object-oriented language, so this is used in cases where the pointer + * could be of either type */ +typedef struct nr_registry_node_ { + unsigned char type; +} nr_registry_node; + +typedef struct nr_scalar_registry_node_ { + unsigned char type; + union { + char _char; + UCHAR _uchar; + INT2 _nr_int2; + UINT2 _nr_uint2; + INT4 _nr_int4; + UINT4 _nr_uint4; + INT8 _nr_int8; + UINT8 _nr_uint8; + double _double; + } scalar; +} nr_scalar_registry_node; + +/* string, bytes */ +typedef struct nr_array_registry_node_ { + unsigned char type; + struct { + unsigned int length; + unsigned char data[1]; + } array; +} nr_array_registry_node; + +static int nr_reg_local_init(nr_registry_module *me); +static int nr_reg_local_get_char(NR_registry name, char *data); +static int nr_reg_local_get_uchar(NR_registry name, UCHAR *data); +static int nr_reg_local_get_int2(NR_registry name, INT2 *data); +static int nr_reg_local_get_uint2(NR_registry name, UINT2 *data); +static int nr_reg_local_get_int4(NR_registry name, INT4 *data); +static int nr_reg_local_get_uint4(NR_registry name, UINT4 *data); +static int nr_reg_local_get_int8(NR_registry name, INT8 *data); +static int nr_reg_local_get_uint8(NR_registry name, UINT8 *data); +static int nr_reg_local_get_double(NR_registry name, double *data); +static int nr_reg_local_get_registry(NR_registry name, NR_registry data); +static int nr_reg_local_get_bytes(NR_registry name, UCHAR *data, size_t size, size_t *length); +static int nr_reg_local_get_string(NR_registry name, char *data, size_t size); +static int nr_reg_local_get_length(NR_registry name, size_t *len); +static int nr_reg_local_get_type(NR_registry name, NR_registry_type type); +static int nr_reg_local_set_char(NR_registry name, char data); +static int nr_reg_local_set_uchar(NR_registry name, UCHAR data); +static int nr_reg_local_set_int2(NR_registry name, INT2 data); +static int nr_reg_local_set_uint2(NR_registry name, UINT2 data); +static int nr_reg_local_set_int4(NR_registry name, INT4 data); +static int nr_reg_local_set_uint4(NR_registry name, UINT4 data); +static int nr_reg_local_set_int8(NR_registry name, INT8 data); +static int nr_reg_local_set_uint8(NR_registry name, UINT8 data); +static int nr_reg_local_set_double(NR_registry name, double data); +static int nr_reg_local_set_registry(NR_registry name); +static int nr_reg_local_set_bytes(NR_registry name, UCHAR *data, size_t length); +static int nr_reg_local_set_string(NR_registry name, char *data); +static int nr_reg_local_del(NR_registry name); +static int nr_reg_local_get_child_count(NR_registry parent, size_t *count); +static int nr_reg_local_get_children(NR_registry parent, NR_registry *data, size_t size, size_t *length); +static int nr_reg_local_fin(NR_registry name); +static int nr_reg_local_dump(int sorted); +static int nr_reg_insert_node(char *name, void *node); +static int nr_reg_change_node(char *name, void *node, void *old); +static int nr_reg_get(char *name, int type, void *out); +static int nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out); +static int nr_reg_get_array(char *name, unsigned char type, UCHAR *out, size_t size, size_t *length); +static int nr_reg_set(char *name, int type, void *data); +static int nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length); +static int nr_reg_set_parent_registries(char *name); + +/* make these static OLD_REGISTRY */ +#if 0 +static int nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node); +static char *nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit); +#else +int nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node); +char *nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit); +#endif +static int nr_reg_rfree(void *ptr); +#if 0 /* Unused currently */ +static int nr_reg_noop(void *ptr); +#endif +static int nr_reg_compute_length(char *name, nr_registry_node *node, size_t *length); +char *nr_reg_action_name(int action); + +/* the registry, containing mappings like "foo.bar.baz" to registry + * nodes, which are either of type nr_scalar_registry_node or + * nr_array_registry_node */ +static r_assoc *nr_registry = 0; + +#if 0 /* Unused currently */ +static nr_array_registry_node nr_top_level_node; +#endif + +typedef struct nr_reg_find_children_arg_ { + size_t size; + NR_registry *children; + size_t length; +} nr_reg_find_children_arg; + +static int nr_reg_local_iter(NR_registry prefix, int (*action)(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node), void *ptr); +static int nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node); +static int nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node); +static int nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node); +static int nr_reg_local_dump_print(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node); + + + +int +nr_reg_local_iter(NR_registry prefix, int (*action)(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node), void *ptr) +{ + int r, _status; + r_assoc_iterator iter; + char *name; + int namel; + nr_registry_node *node; + int prefixl; + + if (prefix == 0) + ABORT(R_INTERNAL); + + if ((r=r_assoc_init_iter(nr_registry, &iter))) + ABORT(r); + + prefixl = strlen(prefix); + + for (;;) { + if ((r=r_assoc_iter(&iter, (void*)&name, &namel, (void*)&node))) { + if (r == R_EOD) + break; + else + ABORT(r); + } + + /* subtract to remove the '\0' character from the string length */ + --namel; + + /* sanity check that the name is null-terminated */ + assert(namel >= 0); + assert(name[namel] == '\0'); + + if (namel < 0 || name[namel] != '\0' || node == 0) + break; + + /* 3 cases where action will be called: + * 1) prefix == "" + * 2) prefix == name + * 3) name == prefix + '.' + */ + if (prefixl == 0 + || ((namel == prefixl || (namel > prefixl && name[prefixl] == '.')) + && !strncmp(prefix, name, prefixl))) { + if ((r=action(ptr, &iter, prefix, name, node))) + ABORT(r); + } + } + + _status=0; + abort: + + return(_status); +} + +int +nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node) +{ + int r, _status; + + if ((r=r_assoc_iter_delete(iter))) + ABORT(r); + + _status=0; + abort: + return(_status); +} + +int +nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node) +{ + int _status; + int prefixl = strlen(prefix); + char *dot; + nr_reg_find_children_arg *arg = (void*)ptr; + + assert(sizeof(*(arg->children)) == sizeof(NR_registry)); + + /* only grovel through immediate children */ + if (prefixl == 0 || name[prefixl] == '.') { + if (name[prefixl] != '\0') { + dot = strchr(&name[prefixl+1], '.'); + if (dot == 0) { + strncpy(arg->children[arg->length], name, sizeof(NR_registry)-1); + ++arg->length; + + /* only grab as many as there are room for */ + if (arg->length >= arg->size) + ABORT(R_INTERRUPTED); + } + } + } + + _status = 0; + abort: + return _status; +} + +int +nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node) +{ + int prefixl = strlen(prefix); + char *dot; + + /* only count children */ + if (name[prefixl] == '.') { + dot = strchr(&name[prefixl+1], '.'); + if (dot == 0) + ++(*(unsigned int *)ptr); + } + else if (name[0] != '\0') { + if (prefixl == 0) + ++(*(unsigned int *)ptr); + } + + return 0; +} + +int +nr_reg_local_dump_print(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node) +{ + int _status; + int freeit = 0; + char *data; + + /* only print leaf nodes */ + if (node->type != NR_REG_TYPE_REGISTRY) { + data = nr_reg_alloc_node_data(name, node, &freeit); + if (ptr) + fprintf((FILE*)ptr, "%s: %s\n", name, data); + else + r_log(NR_LOG_REGISTRY, LOG_INFO, "%s: %s", name, data); + if (freeit) + RFREE(data); + } + + _status=0; + //abort: + return(_status); +} + + +#if 0 /* Unused currently */ +int +nr_reg_noop(void *ptr) +{ + return 0; +} +#endif + +int +nr_reg_rfree(void *ptr) +{ + RFREE(ptr); + return 0; +} + +int +nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node) +{ + int r, _status; + + *node = 0; + *free_node = 0; + + if ((r=nr_reg_is_valid(name))) + ABORT(r); + + if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)node))) + ABORT(r); + + if ((*node)->type != type) + ABORT(R_FAILED); + + _status=0; + abort: + if (_status) { + if (*node) + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't fetch node '%s' ('%s'), found '%s' instead", + name, nr_reg_type_name(type), nr_reg_type_name((*node)->type)); + else + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't fetch node '%s' ('%s')", + name, nr_reg_type_name(type)); + } + else { + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Fetched node '%s' ('%s')", + name, nr_reg_type_name(type)); + } + return(_status); +} + +int +nr_reg_insert_node(char *name, void *node) +{ + int r, _status; + + if ((r=nr_reg_is_valid(name))) + ABORT(r); + + /* since the registry application is not multi-threaded, a node being + * inserted should always be a new node because the registry app must + * have looked for a node with this key but not found it, so it is + * being created/inserted now using R_ASSOC_NEW */ + if ((r=r_assoc_insert(nr_registry, name, strlen(name)+1, node, 0, nr_reg_rfree, R_ASSOC_NEW))) + ABORT(r); + + if ((r=nr_reg_set_parent_registries(name))) + ABORT(r); + + if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_ADD))) + ABORT(r); + + _status=0; + abort: + if (r_logging(NR_LOG_REGISTRY, LOG_INFO)) { + int freeit; + char *data = nr_reg_alloc_node_data(name, (void*)node, &freeit); + r_log(NR_LOG_REGISTRY, LOG_INFO, + "insert '%s' (%s) %s: %s", name, + nr_reg_type_name(((nr_registry_node*)node)->type), + (_status ? "FAILED" : "succeeded"), data); + if (freeit) + RFREE(data); + } + return(_status); +} + +int +nr_reg_change_node(char *name, void *node, void *old) +{ + int r, _status; + + if ((r=nr_reg_is_valid(name))) + ABORT(r); + + if (old != node) { + if ((r=r_assoc_insert(nr_registry, name, strlen(name)+1, node, 0, nr_reg_rfree, R_ASSOC_REPLACE))) + ABORT(r); + } + + if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_CHANGE))) + ABORT(r); + + _status=0; + abort: + if (r_logging(NR_LOG_REGISTRY, LOG_INFO)) { + int freeit; + char *data = nr_reg_alloc_node_data(name, (void*)node, &freeit); + r_log(NR_LOG_REGISTRY, LOG_INFO, + "change '%s' (%s) %s: %s", name, + nr_reg_type_name(((nr_registry_node*)node)->type), + (_status ? "FAILED" : "succeeded"), data); + if (freeit) + RFREE(data); + } + return(_status); +} + +char * +nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit) +{ + char *s = 0; + int len; + int alloc = 0; + unsigned int i; + + *freeit = 0; + + switch (node->type) { + default: + alloc = 100; /* plenty of room for any of the scalar types */ + break; + case NR_REG_TYPE_REGISTRY: + alloc = strlen(name) + 1; + break; + case NR_REG_TYPE_BYTES: + alloc = (2 * ((nr_array_registry_node*)node)->array.length) + 1; + break; + case NR_REG_TYPE_STRING: + alloc = 0; + break; + } + + if (alloc > 0) { + s = (void*)RMALLOC(alloc); + if (!s) + return ""; + + *freeit = 1; + } + + len = alloc; + + switch (node->type) { + case NR_REG_TYPE_CHAR: + i = ((nr_scalar_registry_node*)node)->scalar._char; + if (isprint(i) && ! isspace(i)) + snprintf(s, len, "%c", (char)i); + else + snprintf(s, len, "\\%03o", (char)i); + break; + case NR_REG_TYPE_UCHAR: + snprintf(s, len, "0x%02x", ((nr_scalar_registry_node*)node)->scalar._uchar); + break; + case NR_REG_TYPE_INT2: + snprintf(s, len, "%d", ((nr_scalar_registry_node*)node)->scalar._nr_int2); + break; + case NR_REG_TYPE_UINT2: + snprintf(s, len, "%u", ((nr_scalar_registry_node*)node)->scalar._nr_uint2); + break; + case NR_REG_TYPE_INT4: + snprintf(s, len, "%d", ((nr_scalar_registry_node*)node)->scalar._nr_int4); + break; + case NR_REG_TYPE_UINT4: + snprintf(s, len, "%u", ((nr_scalar_registry_node*)node)->scalar._nr_uint4); + break; + case NR_REG_TYPE_INT8: + snprintf(s, len, "%lld", ((nr_scalar_registry_node*)node)->scalar._nr_int8); + break; + case NR_REG_TYPE_UINT8: + snprintf(s, len, "%llu", ((nr_scalar_registry_node*)node)->scalar._nr_uint8); + break; + case NR_REG_TYPE_DOUBLE: + snprintf(s, len, "%#f", ((nr_scalar_registry_node*)node)->scalar._double); + break; + case NR_REG_TYPE_REGISTRY: + snprintf(s, len, "%s", name); + break; + case NR_REG_TYPE_BYTES: + for (i = 0; i < ((nr_array_registry_node*)node)->array.length; ++i) { + sprintf(&s[2*i], "%02x", ((nr_array_registry_node*)node)->array.data[i]); + } + break; + case NR_REG_TYPE_STRING: + s = (char*)((nr_array_registry_node*)node)->array.data; + break; + default: + assert(0); /* bad value */ + *freeit = 0; + s = ""; + break; + } + + return s; +} + +int +nr_reg_get(char *name, int type, void *out) +{ + int r, _status; + nr_scalar_registry_node *node = 0; + int free_node = 0; + + if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node))) + ABORT(r); + + if ((r=nr_reg_get_data(name, node, out))) + ABORT(r); + + _status=0; + abort: + if (free_node) RFREE(node); + return(_status); +} + +int +nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out) +{ + int _status; + + switch (node->type) { + case NR_REG_TYPE_CHAR: + *(char*)out = node->scalar._char; + break; + case NR_REG_TYPE_UCHAR: + *(UCHAR*)out = node->scalar._uchar; + break; + case NR_REG_TYPE_INT2: + *(INT2*)out = node->scalar._nr_int2; + break; + case NR_REG_TYPE_UINT2: + *(UINT2*)out = node->scalar._nr_uint2; + break; + case NR_REG_TYPE_INT4: + *(INT4*)out = node->scalar._nr_int4; + break; + case NR_REG_TYPE_UINT4: + *(UINT4*)out = node->scalar._nr_uint4; + break; + case NR_REG_TYPE_INT8: + *(INT8*)out = node->scalar._nr_int8; + break; + case NR_REG_TYPE_UINT8: + *(UINT8*)out = node->scalar._nr_uint8; + break; + case NR_REG_TYPE_DOUBLE: + *(double*)out = node->scalar._double; + break; + default: + ABORT(R_INTERNAL); + break; + } + + _status=0; + abort: + return(_status); +} + +int +nr_reg_get_array(char *name, unsigned char type, unsigned char *out, size_t size, size_t *length) +{ + int r, _status; + nr_array_registry_node *node = 0; + int free_node = 0; + + if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node))) + ABORT(r); + + if (size < node->array.length) + ABORT(R_BAD_ARGS); + + if (out != 0) + memcpy(out, node->array.data, node->array.length); + if (length != 0) + *length = node->array.length; + + _status=0; + abort: + if (node && free_node) RFREE(node); + return(_status); +} + +int +nr_reg_set(char *name, int type, void *data) +{ + int r, _status; + nr_scalar_registry_node *node = 0; + int create_node = 0; + int changed = 0; + int free_node = 0; + + if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node))) + if (r == R_NOT_FOUND) { + create_node = 1; + free_node = 1; + } + else + ABORT(r); + + if (create_node) { + if (!(node=(void*)RCALLOC(sizeof(nr_scalar_registry_node)))) + ABORT(R_NO_MEMORY); + + node->type = type; + } + else { + if (node->type != type) + ABORT(R_BAD_ARGS); + } + + switch (type) { +#define CASE(TYPE, _name, type) \ + case TYPE: \ + if (node->scalar._name != *(type*)data) { \ + node->scalar._name = *(type*)data; \ + if (! create_node) \ + changed = 1; \ + } \ + break; + CASE(NR_REG_TYPE_CHAR, _char, char) + CASE(NR_REG_TYPE_UCHAR, _uchar, UCHAR) + CASE(NR_REG_TYPE_INT2, _nr_int2, INT2) + CASE(NR_REG_TYPE_UINT2, _nr_uint2, UINT2) + CASE(NR_REG_TYPE_INT4, _nr_int4, INT4) + CASE(NR_REG_TYPE_UINT4, _nr_uint4, UINT4) + CASE(NR_REG_TYPE_INT8, _nr_int8, INT8) + CASE(NR_REG_TYPE_UINT8, _nr_uint8, UINT8) + CASE(NR_REG_TYPE_DOUBLE, _double, double) +#undef CASE + + case NR_REG_TYPE_REGISTRY: + /* do nothing */ + break; + + default: + ABORT(R_INTERNAL); + break; + } + + if (create_node) { + if ((r=nr_reg_insert_node(name, node))) + ABORT(r); + free_node = 0; + } + else { + if (changed) { + if ((r=nr_reg_change_node(name, node, node))) + ABORT(r); + free_node = 0; + } + } + + _status=0; + abort: + if (_status) { + if (node && free_node) RFREE(node); + } + return(_status); +} + +int +nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length) +{ + int r, _status; + nr_array_registry_node *old = 0; + nr_array_registry_node *node = 0; + int free_node = 0; + int added = 0; + int changed = 0; + + if ((r=nr_reg_fetch_node(name, type, (void*)&old, &free_node))) { + if (r != R_NOT_FOUND) + ABORT(r); + } + else { + assert(free_node == 0); + } + + if (old) { + if (old->type != type) + ABORT(R_BAD_ARGS); + + if (old->array.length != length + || memcmp(old->array.data, data, length)) { + changed = 1; + + if (old->array.length < length) { + if (!(node=(void*)RCALLOC(sizeof(nr_array_registry_node)+length))) + ABORT(R_NO_MEMORY); + } + else { + node = old; + } + } + } + else { + if (!(node=(void*)RCALLOC(sizeof(nr_array_registry_node)+length))) + ABORT(R_NO_MEMORY); + + added = 1; + } + + if (added || changed) { + node->type = type; + node->array.length = length; + memcpy(node->array.data, data, length); + } + + if (added) { + if ((r=nr_reg_insert_node(name, node))) + ABORT(r); + } + else if (changed) { + if ((r=nr_reg_change_node(name, node, old))) + ABORT(r); + } + + _status=0; + abort: + return(_status); +} + +int +nr_reg_set_parent_registries(char *name) +{ + int r, _status; + char *parent = 0; + char *dot; + + if ((parent = r_strdup(name)) == 0) + ABORT(R_NO_MEMORY); + + if ((dot = strrchr(parent, '.')) != 0) { + *dot = '\0'; + if ((r=NR_reg_set_registry(parent))) + ABORT(r); + } + + _status=0; + abort: + if (parent) RFREE(parent); + return(_status); +} + + + + + +/* NON-STATIC METHODS */ + +int +nr_reg_is_valid(NR_registry name) +{ + int _status; + unsigned int length; + unsigned int i; + + if (name == 0) + ABORT(R_BAD_ARGS); + + /* make sure the key is null-terminated */ + if (memchr(name, '\0', sizeof(NR_registry)) == 0) + ABORT(R_BAD_ARGS); + + length = strlen(name); + + /* cannot begin or end with a period */ + if (name[0] == '.') + ABORT(R_BAD_ARGS); + if (strlen(name) > 0 && name[length-1] == '.') + ABORT(R_BAD_ARGS); + + /* all characters cannot be space, and must be printable and not / */ + for (i = 0; i < length; ++i) { + if (isspace(name[i]) || !isprint(name[i]) || name[i] == '/') + ABORT(R_BAD_ARGS); + } + + _status=0; + abort: + if (_status) { + r_log(NR_LOG_REGISTRY, LOG_DEBUG, "invalid name '%s'", name); + } + return(_status); +} + + +int +nr_reg_compute_length(char *name, nr_registry_node *in, size_t *length) +{ + int _status; + nr_array_registry_node *node = (nr_array_registry_node*)in; + + switch (node->type) { + case NR_REG_TYPE_STRING: + *length = node->array.length - 1; + break; + case NR_REG_TYPE_BYTES: + *length = node->array.length; + break; + case NR_REG_TYPE_CHAR: + *length = sizeof(char); + break; + case NR_REG_TYPE_UCHAR: + *length = sizeof(UCHAR); + break; + case NR_REG_TYPE_INT2: + case NR_REG_TYPE_UINT2: + *length = 2; + break; + case NR_REG_TYPE_INT4: + case NR_REG_TYPE_UINT4: + *length = 4; + break; + case NR_REG_TYPE_INT8: + case NR_REG_TYPE_UINT8: + *length = 8; + break; + case NR_REG_TYPE_DOUBLE: + *length = sizeof(double); + break; + case NR_REG_TYPE_REGISTRY: + *length = strlen(name); + break; + default: + ABORT(R_INTERNAL); + break; + } + + _status=0; + abort: + return(_status); +} + + +/* VTBL METHODS */ + +int +nr_reg_local_init(nr_registry_module *me) +{ + int r, _status; + + if (nr_registry == 0) { + if ((r=r_assoc_create(&nr_registry, r_assoc_crc32_hash_compute, 12))) + ABORT(r); + + if ((r=nr_reg_cb_init())) + ABORT(r); + + /* make sure NR_TOP_LEVEL_REGISTRY always exists */ + if ((r=nr_reg_local_set_registry(NR_TOP_LEVEL_REGISTRY))) + ABORT(r); + } + + _status=0; + abort: + return(_status); +} + +#define NRREGLOCALGET(func, TYPE, type) \ +int \ +func(NR_registry name, type *out) \ +{ \ + return nr_reg_get(name, TYPE, out); \ +} + +NRREGLOCALGET(nr_reg_local_get_char, NR_REG_TYPE_CHAR, char) +NRREGLOCALGET(nr_reg_local_get_uchar, NR_REG_TYPE_UCHAR, UCHAR) +NRREGLOCALGET(nr_reg_local_get_int2, NR_REG_TYPE_INT2, INT2) +NRREGLOCALGET(nr_reg_local_get_uint2, NR_REG_TYPE_UINT2, UINT2) +NRREGLOCALGET(nr_reg_local_get_int4, NR_REG_TYPE_INT4, INT4) +NRREGLOCALGET(nr_reg_local_get_uint4, NR_REG_TYPE_UINT4, UINT4) +NRREGLOCALGET(nr_reg_local_get_int8, NR_REG_TYPE_INT8, INT8) +NRREGLOCALGET(nr_reg_local_get_uint8, NR_REG_TYPE_UINT8, UINT8) +NRREGLOCALGET(nr_reg_local_get_double, NR_REG_TYPE_DOUBLE, double) + +int +nr_reg_local_get_registry(NR_registry name, NR_registry out) +{ + int r, _status; + nr_scalar_registry_node *node = 0; + int free_node = 0; + + if ((r=nr_reg_fetch_node(name, NR_REG_TYPE_REGISTRY, (void*)&node, &free_node))) + ABORT(r); + + strncpy(out, name, sizeof(NR_registry)); + + _status=0; + abort: + if (free_node) RFREE(node); + return(_status); + +} + +int +nr_reg_local_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length) +{ + return nr_reg_get_array(name, NR_REG_TYPE_BYTES, out, size, length); +} + +int +nr_reg_local_get_string(NR_registry name, char *out, size_t size) +{ + return nr_reg_get_array(name, NR_REG_TYPE_STRING, (UCHAR*)out, size, 0); +} + +int +nr_reg_local_get_length(NR_registry name, size_t *length) +{ + int r, _status; + nr_registry_node *node = 0; + + if ((r=nr_reg_is_valid(name))) + ABORT(r); + + if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)&node))) + ABORT(r); + + if ((r=nr_reg_compute_length(name, node, length))) + ABORT(r); + + _status=0; + abort: + return(_status); +} + +int +nr_reg_local_get_type(NR_registry name, NR_registry_type type) +{ + int r, _status; + nr_registry_node *node = 0; + char *str; + + if ((r=nr_reg_is_valid(name))) + ABORT(r); + + if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)&node))) + ABORT(r); + + str = nr_reg_type_name(node->type); + if (! str) + ABORT(R_BAD_ARGS); + + strncpy(type, str, sizeof(NR_registry_type)); + + _status=0; + abort: + return(_status); +} + + +#define NRREGLOCALSET(func, TYPE, type) \ +int \ +func(NR_registry name, type data) \ +{ \ + return nr_reg_set(name, TYPE, &data); \ +} + +NRREGLOCALSET(nr_reg_local_set_char, NR_REG_TYPE_CHAR, char) +NRREGLOCALSET(nr_reg_local_set_uchar, NR_REG_TYPE_UCHAR, UCHAR) +NRREGLOCALSET(nr_reg_local_set_int2, NR_REG_TYPE_INT2, INT2) +NRREGLOCALSET(nr_reg_local_set_uint2, NR_REG_TYPE_UINT2, UINT2) +NRREGLOCALSET(nr_reg_local_set_int4, NR_REG_TYPE_INT4, INT4) +NRREGLOCALSET(nr_reg_local_set_uint4, NR_REG_TYPE_UINT4, UINT4) +NRREGLOCALSET(nr_reg_local_set_int8, NR_REG_TYPE_INT8, INT8) +NRREGLOCALSET(nr_reg_local_set_uint8, NR_REG_TYPE_UINT8, UINT8) +NRREGLOCALSET(nr_reg_local_set_double, NR_REG_TYPE_DOUBLE, double) + +int +nr_reg_local_set_registry(NR_registry name) +{ + return nr_reg_set(name, NR_REG_TYPE_REGISTRY, 0); +} + +int +nr_reg_local_set_bytes(NR_registry name, unsigned char *data, size_t length) +{ + return nr_reg_set_array(name, NR_REG_TYPE_BYTES, data, length); +} + +int +nr_reg_local_set_string(NR_registry name, char *data) +{ + return nr_reg_set_array(name, NR_REG_TYPE_STRING, (UCHAR*)data, strlen(data)+1); +} + +int +nr_reg_local_del(NR_registry name) +{ + int r, _status; + + if ((r=nr_reg_is_valid(name))) + ABORT(r); + + /* delete from NR_registry */ + if ((r=nr_reg_local_iter(name, nr_reg_local_iter_delete, 0))) + ABORT(r); + + if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_DELETE))) + ABORT(r); + + /* if deleting from the root, re-insert the root */ + if (! strcasecmp(name, NR_TOP_LEVEL_REGISTRY)) { + if ((r=nr_reg_local_set_registry(NR_TOP_LEVEL_REGISTRY))) + ABORT(r); + } + + _status=0; + abort: + r_log(NR_LOG_REGISTRY, + (_status ? LOG_INFO : LOG_INFO), + "delete of '%s' %s", name, + (_status ? "FAILED" : "succeeded")); + return(_status); +} + +int +nr_reg_local_get_child_count(NR_registry parent, size_t *count) +{ + int r, _status; + nr_registry_node *ignore1; + int ignore2; + + + if ((r=nr_reg_is_valid(parent))) + ABORT(r); + + /* test to see whether it is present */ + if ((r=nr_reg_fetch_node(parent, NR_REG_TYPE_REGISTRY, &ignore1, &ignore2))) + ABORT(r); + + /* sanity check that there isn't any memory to free */ + assert(ignore2 == 0); + + *count = 0; + + if ((r=nr_reg_local_iter(parent, nr_reg_local_count_children, count))) + ABORT(r); + + _status=0; + abort: + return(_status); +} + +int +nr_reg_local_get_children(NR_registry parent, NR_registry *data, size_t size, size_t *length) +{ + int r, _status; + nr_reg_find_children_arg arg; + + if ((r=nr_reg_is_valid(parent))) + ABORT(r); + + arg.children = data; + arg.size = size; + arg.length = 0; + + if ((r=nr_reg_local_iter(parent, nr_reg_local_find_children, (void*)&arg))) { + if (r == R_INTERRUPTED) + ABORT(R_BAD_ARGS); + else + ABORT(r); + } + + assert(sizeof(*arg.children) == sizeof(NR_registry)); + qsort(arg.children, arg.length, sizeof(*arg.children), (void*)strcasecmp); + + *length = arg.length; + + _status = 0; + abort: + return(_status); +} + +int +nr_reg_local_fin(NR_registry name) +{ + int r, _status; + + if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_FINAL))) + ABORT(r); + + _status=0; + abort: + return(_status); +} + +int +nr_reg_local_dump(int sorted) +{ + int r, _status; + + if ((r=nr_reg_local_iter(NR_TOP_LEVEL_REGISTRY, nr_reg_local_dump_print, 0))) + ABORT(r); + + _status=0; + abort: + return(_status); +} + + + +static nr_registry_module_vtbl nr_reg_local_vtbl = { + nr_reg_local_init, + nr_reg_local_get_char, + nr_reg_local_get_uchar, + nr_reg_local_get_int2, + nr_reg_local_get_uint2, + nr_reg_local_get_int4, + nr_reg_local_get_uint4, + nr_reg_local_get_int8, + nr_reg_local_get_uint8, + nr_reg_local_get_double, + nr_reg_local_get_registry, + nr_reg_local_get_bytes, + nr_reg_local_get_string, + nr_reg_local_get_length, + nr_reg_local_get_type, + nr_reg_local_set_char, + nr_reg_local_set_uchar, + nr_reg_local_set_int2, + nr_reg_local_set_uint2, + nr_reg_local_set_int4, + nr_reg_local_set_uint4, + nr_reg_local_set_int8, + nr_reg_local_set_uint8, + nr_reg_local_set_double, + nr_reg_local_set_registry, + nr_reg_local_set_bytes, + nr_reg_local_set_string, + nr_reg_local_del, + nr_reg_local_get_child_count, + nr_reg_local_get_children, + nr_reg_local_fin, + nr_reg_local_dump +}; + +static nr_registry_module nr_reg_local_module = { 0, &nr_reg_local_vtbl }; + +void *NR_REG_MODE_LOCAL = &nr_reg_local_module; + + -- cgit v1.2.3