diff options
author | David Robillard <d@drobilla.net> | 2018-02-04 15:33:36 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 16:27:02 -0500 |
commit | c644f404054e6d68f3bb645cf93b8ad1501b8938 (patch) | |
tree | 6291623c37dd9ef6be062113bf6ac5afa8115171 /src/node.c | |
parent | b0d4ae792c88cc55f9cc9a579530a1a13a158fda (diff) | |
download | serd-c644f404054e6d68f3bb645cf93b8ad1501b8938.tar.gz serd-c644f404054e6d68f3bb645cf93b8ad1501b8938.tar.bz2 serd-c644f404054e6d68f3bb645cf93b8ad1501b8938.zip |
Make nodes opaque
Diffstat (limited to 'src/node.c')
-rw-r--r-- | src/node.c | 184 |
1 files changed, 106 insertions, 78 deletions
@@ -11,6 +11,7 @@ #include "serd/string.h" #include "serd/uri.h" +#include <assert.h> #include <float.h> #include <math.h> #include <stdbool.h> @@ -56,45 +57,67 @@ string_sink(const void* const buf, const size_t len, void* const stream) return len; } -SerdNode -serd_node_from_string(const SerdNodeType type, const char* const str) +SerdNode* +serd_node_malloc(const size_t length, + const SerdNodeFlags flags, + const SerdNodeType type) { - if (!str) { - return SERD_NODE_NULL; - } + SerdNode* node = (SerdNode*)calloc(1, sizeof(SerdNode) + length + 1); + + node->length = 0; + node->flags = flags; + node->type = type; - SerdNodeFlags flags = 0; - const size_t n_bytes = serd_strlen(str, &flags); - const SerdNode ret = {str, n_bytes, flags, type}; - return ret; + return node; } -SerdNode -serd_node_from_substring(const SerdNodeType type, - const char* const str, - const size_t len) +void +serd_node_set(SerdNode** const dst, const SerdNode* const src) { - if (!str) { - return SERD_NODE_NULL; + assert(dst); + assert(src); + + if (!*dst || (*dst)->length < src->length) { + (*dst) = (SerdNode*)realloc(*dst, sizeof(SerdNode) + src->length + 1); } - SerdNodeFlags flags = 0; - const size_t n_bytes = serd_substrlen(str, len, &flags); - const SerdNode ret = {str, n_bytes, flags, type}; - return ret; + memcpy(*dst, src, sizeof(SerdNode) + src->length + 1); +} + +SerdNode* +serd_new_string(SerdNodeType type, const char* str) +{ + SerdNodeFlags flags = 0; + const size_t length = serd_strlen(str, &flags); + SerdNode* node = serd_node_malloc(length, flags, type); + memcpy(serd_node_buffer(node), str, length); + node->length = length; + return node; +} + +SerdNode* +serd_new_substring(const SerdNodeType type, + const char* const str, + const size_t len) +{ + SerdNodeFlags flags = 0; + const size_t length = serd_substrlen(str, len, &flags); + SerdNode* node = serd_node_malloc(length, flags, type); + memcpy(serd_node_buffer(node), str, length); + node->length = length; + return node; } -SerdNode -serd_node_copy(const SerdNode* const node) +SerdNode* +serd_node_copy(const SerdNode* node) { - if (!node || !node->buf) { - return SERD_NODE_NULL; + if (!node) { + return NULL; } - SerdNode copy = *node; - char* buf = (char*)malloc(copy.n_bytes + 1); - memcpy(buf, node->buf, copy.n_bytes + 1); - copy.buf = buf; + const size_t size = sizeof(SerdNode) + node->length + 1; + SerdNode* copy = (SerdNode*)malloc(size); + memcpy(copy, node, size); return copy; } @@ -102,28 +125,29 @@ bool serd_node_equals(const SerdNode* const a, const SerdNode* const b) { return (a == b) || - (a->type == b->type && a->n_bytes == b->n_bytes && - ((a->buf == b->buf) || !memcmp(a->buf, b->buf, a->n_bytes + 1))); + (a && b && a->type == b->type && a->length == b->length && + !memcmp(serd_node_string(a), serd_node_string(b), a->length)); } -SerdNode +SerdNode* serd_new_uri_from_node(const SerdNode* const uri_node, const SerdURIView* const base, SerdURIView* const out) { - return (uri_node->type == SERD_URI && uri_node->buf) - ? serd_new_uri_from_string(uri_node->buf, base, out) - : SERD_NODE_NULL; + const char* uri_str = serd_node_string(uri_node); + return (uri_node && uri_node->type == SERD_URI && uri_str) + ? serd_new_uri_from_string(uri_str, base, out) + : NULL; } -SerdNode +SerdNode* serd_new_uri_from_string(const char* const str, const SerdURIView* const base, SerdURIView* const out) { if (!str || str[0] == '\0') { // Empty URI => Base URI, or nothing if no base is given - return base ? serd_new_uri(base, NULL, out) : SERD_NODE_NULL; + return base ? serd_new_uri(base, NULL, out) : NULL; } SerdURIView uri; @@ -177,7 +201,7 @@ is_dir_sep(const char c) #endif } -SerdNode +SerdNode* serd_new_file_uri(const char* const path, const char* const hostname, SerdURIView* const out) @@ -220,15 +244,18 @@ serd_new_file_uri(const char* const path, } } + const size_t length = buffer.len; const char* const string = serd_buffer_sink_finish(&buffer); - if (string && out) { - serd_uri_parse(string, out); + SerdNode* const node = serd_new_substring(SERD_URI, string, length); + if (out) { + serd_uri_parse(serd_node_buffer(node), out); } - return serd_node_from_substring(SERD_URI, string, buffer.len); + free(buffer.buf); + return node; } -SerdNode +SerdNode* serd_new_uri(const SerdURIView* const uri, const SerdURIView* const base, SerdURIView* const out) @@ -239,22 +266,21 @@ serd_new_uri(const SerdURIView* const uri, } const size_t len = serd_uri_string_length(&abs_uri); - char* buf = (char*)malloc(len + 1); - SerdNode node = {buf, len, 0, SERD_URI}; - char* ptr = buf; + SerdNode* node = serd_node_malloc(len, 0, SERD_URI); + char* ptr = serd_node_buffer(node); const size_t actual_len = serd_uri_serialise(&abs_uri, string_sink, &ptr); - buf[actual_len] = '\0'; - node.n_bytes = actual_len; + serd_node_buffer(node)[actual_len] = '\0'; + node->length = actual_len; if (out) { - serd_uri_parse(buf, out); // TODO: cleverly avoid double parse + serd_uri_parse(serd_node_buffer(node), out); // TODO: avoid double parse } return node; } -SerdNode +SerdNode* serd_new_relative_uri(const SerdURIView* const uri, const SerdURIView* const base, const SerdURIView* const root, @@ -262,17 +288,16 @@ serd_new_relative_uri(const SerdURIView* const uri, { const size_t uri_len = serd_uri_string_length(uri); const size_t base_len = serd_uri_string_length(base); - char* buf = (char*)malloc(uri_len + base_len + 1); - SerdNode node = {buf, 0, 0, SERD_URI}; - char* ptr = buf; + SerdNode* node = serd_node_malloc(uri_len + base_len, 0, SERD_URI); + char* ptr = serd_node_buffer(node); const size_t actual_len = serd_uri_serialise_relative(uri, base, root, string_sink, &ptr); - buf[actual_len] = '\0'; - node.n_bytes = actual_len; + serd_node_buffer(node)[actual_len] = '\0'; + node->length = actual_len; if (out) { - serd_uri_parse(buf, out); // TODO: cleverly avoid double parse + serd_uri_parse(serd_node_buffer(node), out); // TODO: avoid double parse } return node; @@ -285,18 +310,19 @@ serd_digits(const double abs) return lg < 1.0 ? 1U : (unsigned)lg; } -SerdNode +SerdNode* serd_new_decimal(const double d, const unsigned frac_digits) { if (isnan(d) || isinf(d)) { - return SERD_NODE_NULL; + return NULL; } - const double abs_d = fabs(d); - const unsigned int_digits = serd_digits(abs_d); - char* buf = (char*)calloc(int_digits + frac_digits + 3, 1); - SerdNode node = {buf, 0, 0, SERD_LITERAL}; - const double int_part = floor(abs_d); + const double abs_d = fabs(d); + const unsigned int_digits = serd_digits(abs_d); + const size_t len = int_digits + frac_digits + 3; + SerdNode* const node = serd_node_malloc(len, 0, SERD_LITERAL); + char* const buf = serd_node_buffer(node); + const double int_part = floor(abs_d); // Point s to decimal point location char* s = buf + int_digits; @@ -318,7 +344,7 @@ serd_new_decimal(const double d, const unsigned frac_digits) double frac_part = fabs(d - int_part); if (frac_part < DBL_EPSILON) { *s++ = '0'; - node.n_bytes = (size_t)(s - buf); + node->length = (size_t)(s - buf); } else { uint64_t frac = (uint64_t)llround(frac_part * pow(10.0, (int)frac_digits)); s += frac_digits - 1; @@ -328,7 +354,7 @@ serd_new_decimal(const double d, const unsigned frac_digits) for (; i < frac_digits - 1 && !(frac % 10); ++i, --s, frac /= 10) { } - node.n_bytes = (size_t)(s - buf) + 1U; + node->length = (size_t)(s - buf) + 1U; // Write digits from last trailing zero to decimal point for (; i < frac_digits; ++i) { @@ -340,13 +366,13 @@ serd_new_decimal(const double d, const unsigned frac_digits) return node; } -SerdNode +SerdNode* serd_new_integer(const int64_t i) { uint64_t abs_i = (uint64_t)((i < 0) ? -i : i); const unsigned digits = serd_digits((double)abs_i); - char* buf = (char*)calloc(digits + 2, 1); - SerdNode node = {(const char*)buf, 0, 0, SERD_LITERAL}; + SerdNode* node = serd_node_malloc(digits + 2, 0, SERD_LITERAL); + char* buf = serd_node_buffer(node); // Point s to the end char* s = buf + digits - 1; @@ -355,7 +381,7 @@ serd_new_integer(const int64_t i) ++s; } - node.n_bytes = (size_t)(s - buf) + 1U; + node->length = (size_t)(s - buf) + 1U; // Write integer part (right to left) do { @@ -365,17 +391,22 @@ serd_new_integer(const int64_t i) return node; } -SerdNode +SerdNode* serd_new_blob(const void* const buf, const size_t size, const bool wrap_lines) { - const size_t len = serd_base64_get_length(size, wrap_lines); - char* const str = (char*)calloc(len + 2, 1); - SerdNode node = {str, len, 0, SERD_LITERAL}; + if (!buf || !size) { + return NULL; + } - if (serd_base64_encode((uint8_t*)str, buf, size, wrap_lines)) { - node.flags |= SERD_HAS_NEWLINE; + const size_t len = serd_base64_get_length(size, wrap_lines); + SerdNode* const node = serd_node_malloc(len + 1, 0, SERD_LITERAL); + uint8_t* const str = (uint8_t*)serd_node_buffer(node); + + if (serd_base64_encode(str, buf, size, wrap_lines)) { + node->flags |= SERD_HAS_NEWLINE; } + node->length = len; return node; } @@ -388,13 +419,13 @@ serd_node_type(const SerdNode* const node) const char* serd_node_string(const SerdNode* const node) { - return node->buf; + return (const char*)(node + 1); } size_t serd_node_length(const SerdNode* const node) { - return node->n_bytes; + return node->length; } SerdNodeFlags @@ -406,8 +437,5 @@ serd_node_flags(const SerdNode* const node) void serd_node_free(SerdNode* const node) { - if (node && node->buf) { - free((char*)node->buf); - node->buf = NULL; - } + free(node); } |