aboutsummaryrefslogtreecommitdiffstats
path: root/src/env.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2023-09-10 15:06:42 -0400
committerDavid Robillard <d@drobilla.net>2023-12-02 18:49:08 -0500
commit248a874d7425749d29cf900a1c3783c624ea8d8c (patch)
treeaed59f5a484a815cd254506866e98a947858904d /src/env.c
parent0bd10132c6707353dba80bd89cf0102ee7ca4e34 (diff)
downloadserd-248a874d7425749d29cf900a1c3783c624ea8d8c.tar.gz
serd-248a874d7425749d29cf900a1c3783c624ea8d8c.tar.bz2
serd-248a874d7425749d29cf900a1c3783c624ea8d8c.zip
Add support for custom allocators
This makes it explicit in the API where memory is allocated, and allows the user to provide a custom allocator to avoid the use of the default system allocator for whatever reason.
Diffstat (limited to 'src/env.c')
-rw-r--r--src/env.c134
1 files changed, 92 insertions, 42 deletions
diff --git a/src/env.c b/src/env.c
index e9af7d77..90924cd2 100644
--- a/src/env.c
+++ b/src/env.c
@@ -4,6 +4,7 @@
#include "serd/env.h"
#include "env.h"
+#include "memory.h"
#include "node.h"
#include "serd/node.h"
@@ -11,8 +12,6 @@
#include <assert.h>
#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
typedef struct {
@@ -21,42 +20,69 @@ typedef struct {
} SerdPrefix;
struct SerdEnvImpl {
- SerdPrefix* prefixes;
- size_t n_prefixes;
- SerdNode* base_uri_node;
- SerdURIView base_uri;
+ SerdAllocator* allocator;
+ SerdPrefix* prefixes;
+ size_t n_prefixes;
+ SerdNode* base_uri_node;
+ SerdURIView base_uri;
};
SerdEnv*
-serd_env_new(const SerdStringView base_uri)
+serd_env_new(SerdAllocator* const allocator, const SerdStringView base_uri)
{
- SerdEnv* env = (SerdEnv*)calloc(1, sizeof(struct SerdEnvImpl));
- if (env && base_uri.length) {
- serd_env_set_base_uri(env, base_uri);
+ SerdEnv* env =
+ (SerdEnv*)serd_acalloc(allocator, 1, sizeof(struct SerdEnvImpl));
+
+ if (env) {
+ env->allocator = allocator;
+
+ if (base_uri.length) {
+ if (serd_env_set_base_uri(env, base_uri)) {
+ serd_afree(allocator, env);
+ return NULL;
+ }
+ }
}
return env;
}
SerdEnv*
-serd_env_copy(const SerdEnv* const env)
+serd_env_copy(SerdAllocator* const allocator, const SerdEnv* const env)
{
if (!env) {
return NULL;
}
- SerdEnv* copy = (SerdEnv*)calloc(1, sizeof(struct SerdEnvImpl));
+ SerdEnv* const copy =
+ (SerdEnv*)serd_acalloc(allocator, 1, sizeof(struct SerdEnvImpl));
+
if (copy) {
+ copy->allocator = allocator;
copy->n_prefixes = env->n_prefixes;
- copy->prefixes = (SerdPrefix*)malloc(copy->n_prefixes * sizeof(SerdPrefix));
+
+ if (!(copy->prefixes = (SerdPrefix*)serd_acalloc(
+ allocator, copy->n_prefixes, sizeof(SerdPrefix)))) {
+ serd_afree(allocator, copy);
+ return NULL;
+ }
+
for (size_t i = 0; i < copy->n_prefixes; ++i) {
- copy->prefixes[i].name = serd_node_copy(env->prefixes[i].name);
- copy->prefixes[i].uri = serd_node_copy(env->prefixes[i].uri);
+ if (!(copy->prefixes[i].name =
+ serd_node_copy(allocator, env->prefixes[i].name)) ||
+ !(copy->prefixes[i].uri =
+ serd_node_copy(allocator, env->prefixes[i].uri))) {
+ serd_env_free(copy);
+ return NULL;
+ }
}
const SerdNode* const base = serd_env_base_uri(env);
if (base) {
- serd_env_set_base_uri(copy, serd_node_string_view(base));
+ if (serd_env_set_base_uri(copy, serd_node_string_view(base))) {
+ serd_env_free(copy);
+ return NULL;
+ }
}
}
@@ -71,12 +97,12 @@ serd_env_free(SerdEnv* const env)
}
for (size_t i = 0; i < env->n_prefixes; ++i) {
- serd_node_free(env->prefixes[i].name);
- serd_node_free(env->prefixes[i].uri);
+ serd_node_free(env->allocator, env->prefixes[i].name);
+ serd_node_free(env->allocator, env->prefixes[i].uri);
}
- free(env->prefixes);
- serd_node_free(env->base_uri_node);
- free(env);
+ serd_afree(env->allocator, env->prefixes);
+ serd_node_free(env->allocator, env->base_uri_node);
+ serd_afree(env->allocator, env);
}
bool
@@ -119,7 +145,7 @@ serd_env_set_base_uri(SerdEnv* const env, const SerdStringView uri)
assert(env);
if (!uri.length) {
- serd_node_free(env->base_uri_node);
+ serd_node_free(env->allocator, env->base_uri_node);
env->base_uri_node = NULL;
env->base_uri = SERD_URI_NULL;
return SERD_SUCCESS;
@@ -132,10 +158,14 @@ serd_env_set_base_uri(SerdEnv* const env, const SerdStringView uri)
serd_resolve_uri(serd_parse_uri(uri.data), env->base_uri);
// Replace the current base URI
- env->base_uri_node = serd_new_parsed_uri(new_base_uri);
- env->base_uri = serd_node_uri_view(env->base_uri_node);
+ if ((env->base_uri_node =
+ serd_new_parsed_uri(env->allocator, new_base_uri))) {
+ env->base_uri = serd_node_uri_view(env->base_uri_node);
+ } else {
+ return SERD_BAD_ALLOC;
+ }
- serd_node_free(old_base_uri);
+ serd_node_free(env->allocator, old_base_uri);
return SERD_SUCCESS;
}
@@ -170,7 +200,7 @@ serd_env_find(const SerdEnv* const env,
return NULL;
}
-static void
+static SerdStatus
serd_env_add(SerdEnv* const env,
const SerdStringView name,
const SerdStringView uri)
@@ -178,18 +208,34 @@ serd_env_add(SerdEnv* const env,
SerdPrefix* const prefix = serd_env_find(env, name.data, name.length);
if (prefix) {
if (!!strcmp(serd_node_string(prefix->uri), uri.data)) {
- serd_node_free(prefix->uri);
- prefix->uri = serd_new_uri(uri);
+ serd_node_free(env->allocator, prefix->uri);
+ prefix->uri = serd_new_uri(env->allocator, uri);
}
} else {
- SerdPrefix* const new_prefixes = (SerdPrefix*)realloc(
- env->prefixes, (++env->n_prefixes) * sizeof(SerdPrefix));
- if (new_prefixes) {
- env->prefixes = new_prefixes;
- env->prefixes[env->n_prefixes - 1].name = serd_new_string(name);
- env->prefixes[env->n_prefixes - 1].uri = serd_new_uri(uri);
+ SerdPrefix* const new_prefixes =
+ (SerdPrefix*)serd_arealloc(env->allocator,
+ env->prefixes,
+ (env->n_prefixes + 1) * sizeof(SerdPrefix));
+ if (!new_prefixes) {
+ return SERD_BAD_ALLOC;
}
+
+ env->prefixes = new_prefixes;
+
+ SerdNode* const name_node = serd_new_string(env->allocator, name);
+ SerdNode* const uri_node = serd_new_uri(env->allocator, uri);
+ if (!name_node || !uri_node) {
+ serd_node_free(env->allocator, uri_node);
+ serd_node_free(env->allocator, name_node);
+ return SERD_BAD_ALLOC;
+ }
+
+ new_prefixes[env->n_prefixes].name = name_node;
+ new_prefixes[env->n_prefixes].uri = uri_node;
+ ++env->n_prefixes;
}
+
+ return SERD_SUCCESS;
}
SerdStatus
@@ -201,8 +247,7 @@ serd_env_set_prefix(SerdEnv* const env,
if (serd_uri_string_has_scheme(uri.data)) {
// Set prefix to absolute URI
- serd_env_add(env, name, uri);
- return SERD_SUCCESS;
+ return serd_env_add(env, name, uri);
}
if (!env->base_uri_node) {
@@ -215,13 +260,17 @@ serd_env_set_prefix(SerdEnv* const env,
assert(abs_uri_view.scheme.length);
// Create a new node for the absolute URI
- SerdNode* const abs_uri = serd_new_parsed_uri(abs_uri_view);
+ SerdNode* const abs_uri = serd_new_parsed_uri(env->allocator, abs_uri_view);
+ if (!abs_uri) {
+ return SERD_BAD_ALLOC;
+ }
+
assert(serd_uri_string_has_scheme(serd_node_string(abs_uri)));
// Set prefix to resolved (absolute) URI
- serd_env_add(env, name, serd_node_string_view(abs_uri));
- serd_node_free(abs_uri);
- return SERD_SUCCESS;
+ const SerdStatus st = serd_env_add(env, name, serd_node_string_view(abs_uri));
+ serd_node_free(env->allocator, abs_uri);
+ return st;
}
SerdStatus
@@ -290,7 +339,7 @@ serd_env_expand_curie(const SerdEnv* const env, const SerdStringView curie)
}
const size_t len = prefix.length + suffix.length;
- SerdNode* const ret = serd_node_malloc(len, 0U, SERD_URI);
+ SerdNode* const ret = serd_node_malloc(env->allocator, len, 0U, SERD_URI);
if (ret) {
char* const string = serd_node_buffer(ret);
memcpy(string, prefix.data, prefix.length);
@@ -310,7 +359,8 @@ serd_env_expand_node(const SerdEnv* const env, const SerdNode* const node)
const SerdURIView uri = serd_node_uri_view(node);
const SerdURIView abs_uri = serd_resolve_uri(uri, env->base_uri);
- return abs_uri.scheme.length ? serd_new_parsed_uri(abs_uri) : NULL;
+ return abs_uri.scheme.length ? serd_new_parsed_uri(env->allocator, abs_uri)
+ : NULL;
}
SerdStatus