diff options
-rw-r--r-- | include/dom/core/node.h | 17 | ||||
-rw-r--r-- | src/core/node.c | 4 | ||||
-rw-r--r-- | src/utils/Makefile | 3 | ||||
-rw-r--r-- | src/utils/refcheck.c | 69 |
4 files changed, 88 insertions, 5 deletions
diff --git a/include/dom/core/node.h b/include/dom/core/node.h index 90026a1..37fd2b8 100644 --- a/include/dom/core/node.h +++ b/include/dom/core/node.h @@ -73,12 +73,18 @@ typedef enum { typedef struct dom_node_internal dom_node_internal; +struct dom_refcheck; +struct dom_refcheck *dom_refcheck( + struct dom_refcheck *rc, + uint32_t refcnt); + /** * DOM node type */ typedef struct dom_node { const void *vtable; uint32_t refcnt; + struct dom_refcheck *rc; } dom_node; /* DOM node vtable */ @@ -177,9 +183,11 @@ typedef struct dom_node_vtable { static inline dom_node *dom_node_ref(dom_node *node) { - if (node != NULL) + if (node != NULL) { node->refcnt++; - + node->rc = dom_refcheck(node->rc, node->refcnt); + } + return node; } @@ -195,10 +203,11 @@ static inline dom_exception dom_node_try_destroy(dom_node *node) static inline void dom_node_unref(dom_node *node) { if (node != NULL) { - if (--node->refcnt == 0) + node->refcnt--; + node->rc = dom_refcheck(node->rc, node->refcnt); + if (node->refcnt == 0) dom_node_try_destroy(node); } - } #define dom_node_unref(n) dom_node_unref((dom_node *) (n)) diff --git a/src/core/node.c b/src/core/node.c index 1218742..0e3f818 100644 --- a/src/core/node.c +++ b/src/core/node.c @@ -199,7 +199,9 @@ dom_exception _dom_node_initialise(dom_node_internal *node, node->user_data = NULL; + node->base.rc = dom_refcheck(NULL, 0); node->base.refcnt = 1; + node->base.rc = dom_refcheck(node->base.rc, node->base.refcnt); list_init(&node->pending_list); if (node->type != DOM_DOCUMENT_NODE) { @@ -1904,7 +1906,9 @@ dom_exception _dom_node_copy_internal(dom_node_internal *old, new->prefix = NULL; new->user_data = NULL; + new->base.rc = dom_refcheck(NULL, 0); new->base.refcnt = 1; + new->base.rc = dom_refcheck(new->base.rc, new->base.refcnt); list_init(&new->pending_list); diff --git a/src/utils/Makefile b/src/utils/Makefile index f891b6e..027e3a5 100644 --- a/src/utils/Makefile +++ b/src/utils/Makefile @@ -1,4 +1,5 @@ # Sources -DIR_SOURCES := namespace.c hashtable.c character_valid.c validate.c walk.c +DIR_SOURCES := namespace.c hashtable.c character_valid.c validate.c walk.c \ + refcheck.c include $(NSBUILD)/Makefile.subdir diff --git a/src/utils/refcheck.c b/src/utils/refcheck.c new file mode 100644 index 0000000..fbba568 --- /dev/null +++ b/src/utils/refcheck.c @@ -0,0 +1,69 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2021 Michael Drake <tlsa@netsurf-browser.org> + */ + +/** \file + * This is an API for walking a loaded DOM. + */ + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> + +#include <dom/dom.h> + +struct dom_refcheck { + size_t len; + uintptr_t *array; +}; + +struct dom_refcheck *dom_refcheck( + struct dom_refcheck *rc, + uint32_t refcnt) +{ + if (rc == NULL) { + rc = calloc(1, sizeof(*rc)); + if (rc == NULL) { + goto out; + } + + if (refcnt == 0) { + goto out; + } + } + + fprintf(stderr, "%p: refcnt: %u, len: %zu\n", rc, refcnt, rc->len); + + if (refcnt == rc->len - 1) { + //rc->array[refcnt] ^= UINTPTR_MAX; + free((void *)rc->array[refcnt]); + rc->array[refcnt] = (uintptr_t)NULL; + rc->len = refcnt; + + } else if (refcnt == rc->len + 1) { + uintptr_t *temp = realloc(rc->array, sizeof(*temp) * refcnt); + if (temp == NULL) { + goto out; + } + rc->array = temp; + + rc->array[rc->len] = (uintptr_t)malloc(1); + //rc->array[rc->len] ^= UINTPTR_MAX; + rc->len = refcnt; + } + + if (refcnt == 0) { + free(rc->array); + free(rc); + rc = NULL; + goto out; + + } else { + } + +out: + return rc; +} |