diff options
author | David Robillard <d@drobilla.net> | 2018-02-04 15:33:36 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2022-01-13 15:33:54 -0500 |
commit | cda46ec67d41fb120809d5d1d16c05eb1b3882da (patch) | |
tree | a968e71f84289c3ce96b654e9bc285812c17f7d4 /src/node.c | |
parent | a650d2ad2d4785c40405854740e70f487ae1016a (diff) | |
download | serd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.tar.gz serd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.tar.bz2 serd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.zip |
Make nodes opaque
Diffstat (limited to 'src/node.c')
-rw-r--r-- | src/node.c | 180 |
1 files changed, 104 insertions, 76 deletions
@@ -66,45 +66,68 @@ 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; + if (src) { + if (!(*dst) || (*dst)->length < src->length) { + (*dst) = (SerdNode*)realloc(*dst, sizeof(SerdNode) + src->length + 1); + } + + memcpy(*dst, src, sizeof(SerdNode) + src->length + 1); + } else if (*dst) { + memset(*dst, 0, sizeof(SerdNode)); } +} + +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; +} - SerdNodeFlags flags = 0; - const size_t n_bytes = serd_substrlen(str, len, &flags); - const SerdNode ret = {str, n_bytes, flags, type}; - return ret; +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; } @@ -112,28 +135,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_uri_path_char(const char c) } } -SerdNode +SerdNode* serd_new_file_uri(const char* const path, const char* const hostname, SerdURIView* const out) @@ -219,15 +243,17 @@ serd_new_file_uri(const char* const path, } serd_buffer_sink_finish(&buffer); + SerdNode* node = + serd_new_substring(SERD_URI, (const char*)buffer.buf, buffer.len); if (out) { - serd_uri_parse((const char*)buffer.buf, out); + serd_uri_parse(serd_node_buffer(node), out); } - return serd_node_from_substring( - SERD_URI, (const char*)buffer.buf, buffer.len); + free(buffer.buf); + return node; } -SerdNode +SerdNode* serd_new_uri(const SerdURIView* const uri, const SerdURIView* const base, SerdURIView* const out) @@ -238,22 +264,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, @@ -261,17 +286,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; @@ -284,18 +308,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; @@ -317,7 +342,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; @@ -327,7 +352,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) { @@ -339,13 +364,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 = (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; @@ -354,7 +379,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 { @@ -364,16 +389,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) { + if (!buf || !size) { + return NULL; + } + const size_t len = serd_base64_get_length(size, wrap_lines); - uint8_t* str = (uint8_t*)calloc(len + 2, 1); - SerdNode node = {(const char*)str, len, 0, SERD_LITERAL}; + SerdNode* node = serd_node_malloc(len + 1, 0, SERD_LITERAL); + uint8_t* str = (uint8_t*)serd_node_buffer(node); if (serd_base64_encode(str, buf, size, wrap_lines)) { - node.flags |= SERD_HAS_NEWLINE; + node->flags |= SERD_HAS_NEWLINE; } + + node->length = len; return node; } @@ -386,13 +417,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 @@ -404,8 +435,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); } |