diff options
author | David Robillard <d@drobilla.net> | 2023-09-10 15:06:42 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 18:49:08 -0500 |
commit | 248a874d7425749d29cf900a1c3783c624ea8d8c (patch) | |
tree | aed59f5a484a815cd254506866e98a947858904d /src/env.c | |
parent | 0bd10132c6707353dba80bd89cf0102ee7ca4e34 (diff) | |
download | serd-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.c | 134 |
1 files changed, 92 insertions, 42 deletions
@@ -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 |