aboutsummaryrefslogtreecommitdiffstats
path: root/src/nodes.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2021-10-27 14:15:31 -0400
committerDavid Robillard <d@drobilla.net>2022-01-28 21:57:24 -0500
commit30487c277ac5d4be5786733ca7b98adb4c810ae9 (patch)
treef1b00a7725d74a594fcd91de2aea924485356528 /src/nodes.c
parent56cceb103dc633d6af957472945e792187a5dd4e (diff)
downloadserd-30487c277ac5d4be5786733ca7b98adb4c810ae9.tar.gz
serd-30487c277ac5d4be5786733ca7b98adb4c810ae9.tar.bz2
serd-30487c277ac5d4be5786733ca7b98adb4c810ae9.zip
Add custom allocator support
Diffstat (limited to 'src/nodes.c')
-rw-r--r--src/nodes.c103
1 files changed, 66 insertions, 37 deletions
diff --git a/src/nodes.c b/src/nodes.c
index 529af688..09b63f2a 100644
--- a/src/nodes.c
+++ b/src/nodes.c
@@ -16,9 +16,9 @@
#include "nodes.h"
+#include "memory.h"
#include "node.h"
#include "node_spec.h"
-#include "system.h"
// Define the types used in the hash interface for more type safety
#define ZIX_HASH_KEY_TYPE SerdNode
@@ -26,13 +26,13 @@
#define ZIX_HASH_SEARCH_DATA_TYPE NodeSpec
#include "serd/serd.h"
+#include "zix/allocator.h"
#include "zix/digest.h"
#include "zix/hash.h"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
-#include <stdlib.h>
#include <string.h>
#if ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112l) || \
@@ -76,7 +76,8 @@ typedef struct {
} StaticNode;
struct SerdNodesImpl {
- ZixHash* hash;
+ SerdAllocator* allocator;
+ ZixHash* hash;
};
static const StaticNode empty_static_node = {{0u, 0u, SERD_LITERAL}, {'\0'}};
@@ -185,10 +186,10 @@ nodes_equal(const SerdNode* const a, const SerdNode* const b)
}
static NodesEntry*
-new_entry(const size_t node_size)
+new_entry(SerdAllocator* const allocator, const size_t node_size)
{
- NodesEntry* const entry = (NodesEntry*)serd_calloc_aligned(
- serd_node_align, sizeof(NodesEntryHead) + node_size);
+ NodesEntry* const entry = (NodesEntry*)serd_aaligned_calloc(
+ allocator, serd_node_align, sizeof(NodesEntryHead) + node_size);
if (entry) {
entry->head.refs = 1u;
@@ -198,11 +199,20 @@ new_entry(const size_t node_size)
}
SerdNodes*
-serd_nodes_new(void)
+serd_nodes_new(SerdAllocator* const allocator)
{
- SerdNodes* const nodes = (SerdNodes*)calloc(1, sizeof(SerdNodes));
+ SerdNodes* const nodes =
+ (SerdNodes*)serd_acalloc(allocator, 1, sizeof(SerdNodes));
- nodes->hash = zix_hash_new(NULL, nodes_key, nodes_hash, nodes_equal);
+ if (nodes) {
+ nodes->allocator = allocator;
+
+ if (!(nodes->hash = zix_hash_new(
+ (ZixAllocator*)allocator, nodes_key, nodes_hash, nodes_equal))) {
+ serd_afree(allocator, nodes);
+ return NULL;
+ }
+ }
return nodes;
}
@@ -214,11 +224,11 @@ serd_nodes_free(SerdNodes* nodes)
for (ZixHashIter i = zix_hash_begin(nodes->hash);
i != zix_hash_end(nodes->hash);
i = zix_hash_next(nodes->hash, i)) {
- serd_free_aligned(zix_hash_get(nodes->hash, i));
+ serd_aaligned_free(nodes->allocator, zix_hash_get(nodes->hash, i));
}
zix_hash_free(nodes->hash);
- free(nodes);
+ serd_afree(nodes->allocator, nodes);
}
}
@@ -247,7 +257,10 @@ serd_nodes_intern(SerdNodes* nodes, const SerdNode* node)
}
const size_t node_size = serd_node_total_size(node);
- NodesEntry* const entry = new_entry(node_size);
+ NodesEntry* const entry = new_entry(nodes->allocator, node_size);
+ if (!entry) {
+ return NULL;
+ }
memcpy(&entry->node, node, node_size);
@@ -273,6 +286,10 @@ serd_nodes_get(const SerdNodes* const nodes, const SerdNode* const node)
static const SerdNode*
serd_nodes_manage_entry(SerdNodes* const nodes, NodesEntry* const entry)
{
+ if (!entry) {
+ return NULL;
+ }
+
const SerdNode* const node = &entry->node;
const ZixHashInsertPlan plan = zix_hash_plan_insert(nodes->hash, node);
NodesEntry* const existing = zix_hash_record_at(nodes->hash, plan);
@@ -280,12 +297,16 @@ serd_nodes_manage_entry(SerdNodes* const nodes, NodesEntry* const entry)
assert(serd_node_equals(&existing->node, node));
assert(nodes_hash(&existing->node) == plan.code);
++existing->head.refs;
- serd_free_aligned(entry);
+ serd_aaligned_free(nodes->allocator, entry);
return &existing->node;
}
- // Insert the entry (blissfully ignoring a failed hash size increase)
- zix_hash_insert_at(nodes->hash, plan, entry);
+ // Insert the entry (or fail and free it on a failed hash size increase)
+ if (zix_hash_insert_at(nodes->hash, plan, entry)) {
+ serd_aaligned_free(nodes->allocator, entry);
+ return NULL;
+ }
+
assert(nodes_hash(&entry->node) == plan.code);
return &entry->node;
}
@@ -309,22 +330,27 @@ serd_nodes_token(SerdNodes* const nodes,
const size_t padded_length = serd_node_pad_length(string.len);
const size_t node_size = sizeof(SerdNode) + padded_length;
- NodesEntry* const entry = new_entry(node_size);
+ NodesEntry* const entry = new_entry(nodes->allocator, node_size);
SerdNode* const node = entry ? &entry->node : NULL;
+ if (!node) {
+ return NULL;
+ }
- if (node) {
- // Construct the token directly into the node in the new entry
- const SerdWriteResult r =
- serd_node_construct_token(node_size, &entry->node, type, string);
+ // Construct the token directly into the node in the new entry
+ const SerdWriteResult r =
+ serd_node_construct_token(node_size, &entry->node, type, string);
- assert(!r.status); // Never fails with sufficient space
- (void)r;
+ assert(!r.status); // Never fails with sufficient space
+ (void)r;
- // Insert the entry (blissfully ignoring a failed hash size increase)
- zix_hash_insert_at(nodes->hash, plan, entry);
- assert(nodes_hash(node) == code);
+ // Insert the entry (blissfully ignoring a failed hash size increase)
+ if (zix_hash_insert_at(nodes->hash, plan, entry)) {
+ serd_aaligned_free(nodes->allocator, entry);
+ return NULL;
}
+ assert(nodes_hash(node) == code);
+
return node;
}
@@ -357,7 +383,7 @@ serd_nodes_literal(SerdNodes* const nodes,
}
// Allocate a new entry with enough space for the node
- NodesEntry* const entry = new_entry(r.count);
+ NodesEntry* const entry = new_entry(nodes->allocator, r.count);
SerdNode* const node = entry ? &entry->node : NULL;
if (node) {
@@ -460,13 +486,15 @@ serd_nodes_base64(SerdNodes* const nodes,
serd_node_construct_base64(0, NULL, value_size, value, datatype);
// Allocate a new entry to and construct the node into it
- NodesEntry* const entry = new_entry(r.count);
+ NodesEntry* const entry = new_entry(nodes->allocator, r.count);
+ if (entry) {
+ r = serd_node_construct_base64(
+ r.count, &entry->node, value_size, value, datatype);
- r = serd_node_construct_base64(
- r.count, &entry->node, value_size, value, datatype);
+ assert(!r.status);
+ (void)r;
+ }
- assert(!r.status);
- (void)r;
return serd_nodes_manage_entry(nodes, entry);
}
@@ -490,11 +518,12 @@ serd_nodes_parsed_uri(SerdNodes* const nodes, const SerdURIView uri)
assert(r.status == SERD_OVERFLOW); // Currently no other errors
// Allocate a new entry to write the URI node into
- NodesEntry* const entry = new_entry(r.count);
-
- r = serd_node_construct_uri(r.count, &entry->node, uri);
- assert(!r.status);
- (void)r;
+ NodesEntry* const entry = new_entry(nodes->allocator, r.count);
+ if (entry) {
+ r = serd_node_construct_uri(r.count, &entry->node, uri);
+ assert(!r.status);
+ (void)r;
+ }
return serd_nodes_manage_entry(nodes, entry);
}
@@ -522,6 +551,6 @@ serd_nodes_deref(SerdNodes* const nodes, const SerdNode* const node)
NodesEntry* removed = NULL;
zix_hash_erase(nodes->hash, i, &removed);
assert(removed == entry);
- serd_free_aligned(removed);
+ serd_aaligned_free(nodes->allocator, removed);
}
}