diff options
author | David Robillard <d@drobilla.net> | 2018-02-04 15:33:36 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2021-03-07 15:32:24 -0500 |
commit | b2b4fa05b73c6eee51ee9db59726fc404198111a (patch) | |
tree | ce2c1b9f0d6e460dde8d439d684598a6ebe1e703 /src/node.c | |
parent | ecbc7584a09059ab5987dca95a998c88de8b479a (diff) | |
download | serd-b2b4fa05b73c6eee51ee9db59726fc404198111a.tar.gz serd-b2b4fa05b73c6eee51ee9db59726fc404198111a.tar.bz2 serd-b2b4fa05b73c6eee51ee9db59726fc404198111a.zip |
Make nodes opaque
Diffstat (limited to 'src/node.c')
-rw-r--r-- | src/node.c | 172 |
1 files changed, 98 insertions, 74 deletions
@@ -38,43 +38,62 @@ # endif #endif -SerdNode -serd_node_from_string(SerdNodeType type, const char* str) +SerdNode* +serd_node_malloc(size_t n_bytes, SerdNodeFlags flags, SerdNodeType type) { - if (!str) { - return SERD_NODE_NULL; - } - - SerdNodeFlags flags = 0; - const size_t n_bytes = serd_strlen(str, &flags); - const SerdNode ret = {str, n_bytes, flags, type}; - return ret; + SerdNode* node = (SerdNode*)calloc(1, sizeof(SerdNode) + n_bytes + 1); + node->n_bytes = 0; + node->flags = flags; + node->type = type; + return node; } -SerdNode -serd_node_from_substring(SerdNodeType type, const char* str, const size_t len) +void +serd_node_set(SerdNode** dst, const SerdNode* src) { - if (!str) { - return SERD_NODE_NULL; + if (src) { + if (!(*dst) || (*dst)->n_bytes < src->n_bytes) { + (*dst) = (SerdNode*)realloc(*dst, sizeof(SerdNode) + src->n_bytes + 1); + } + + memcpy(*dst, src, sizeof(SerdNode) + src->n_bytes + 1); + } else if (*dst) { + memset(*dst, 0, sizeof(SerdNode)); } +} + +SerdNode* +serd_new_string(SerdNodeType type, const char* str) +{ + SerdNodeFlags flags = 0; + const size_t n_bytes = serd_strlen(str, &flags); + SerdNode* node = serd_node_malloc(n_bytes, flags, type); + memcpy(serd_node_buffer(node), str, n_bytes); + node->n_bytes = n_bytes; + 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(SerdNodeType type, const char* str, const size_t len) +{ + SerdNodeFlags flags = 0; + const size_t n_bytes = serd_substrlen(str, len, &flags); + SerdNode* node = serd_node_malloc(n_bytes, flags, type); + memcpy(serd_node_buffer(node), str, n_bytes); + node->n_bytes = n_bytes; + return node; } -SerdNode +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->n_bytes + 1; + SerdNode* copy = (SerdNode*)malloc(size); + memcpy(copy, node, size); return copy; } @@ -82,8 +101,8 @@ bool serd_node_equals(const SerdNode* a, const SerdNode* 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->n_bytes == b->n_bytes && + !memcmp(serd_node_string(a), serd_node_string(b), a->n_bytes)); } static size_t @@ -114,24 +133,25 @@ string_sink(const void* buf, size_t len, void* stream) return len; } -SerdNode +SerdNode* serd_new_uri_from_node(const SerdNode* uri_node, const SerdURIView* base, SerdURIView* 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* str, const SerdURIView* base, SerdURIView* 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; @@ -175,7 +195,7 @@ is_uri_path_char(const char c) } } -SerdNode +SerdNode* serd_new_file_uri(const char* path, const char* hostname, SerdURIView* out) { const size_t path_len = strlen(path); @@ -215,15 +235,17 @@ serd_new_file_uri(const char* path, const char* hostname, SerdURIView* out) } 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* uri, const SerdURIView* base, SerdURIView* out) { SerdURIView abs_uri = *uri; @@ -232,22 +254,21 @@ serd_new_uri(const SerdURIView* uri, const SerdURIView* base, SerdURIView* out) } 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->n_bytes = 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* uri, const SerdURIView* base, const SerdURIView* root, @@ -255,17 +276,16 @@ serd_new_relative_uri(const SerdURIView* 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->n_bytes = 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; @@ -278,18 +298,19 @@ serd_digits(double abs) return lg < 1.0 ? 1U : (unsigned)lg; } -SerdNode +SerdNode* serd_new_decimal(double d, 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; @@ -310,8 +331,8 @@ serd_new_decimal(double d, unsigned frac_digits) // Write fractional part (right to left) double frac_part = fabs(d - int_part); if (frac_part < DBL_EPSILON) { - *s++ = '0'; - node.n_bytes = (size_t)(s - buf); + *s++ = '0'; + node->n_bytes = (size_t)(s - buf); } else { uint64_t frac = (uint64_t)llround(frac_part * pow(10.0, (int)frac_digits)); s += frac_digits - 1; @@ -321,7 +342,7 @@ serd_new_decimal(double d, unsigned frac_digits) for (; i < frac_digits - 1 && !(frac % 10); ++i, --s, frac /= 10) { } - node.n_bytes = (size_t)(s - buf) + 1u; + node->n_bytes = (size_t)(s - buf) + 1u; // Write digits from last trailing zero to decimal point for (; i < frac_digits; ++i) { @@ -333,13 +354,13 @@ serd_new_decimal(double d, unsigned frac_digits) return node; } -SerdNode +SerdNode* serd_new_integer(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; @@ -348,7 +369,7 @@ serd_new_integer(int64_t i) ++s; } - node.n_bytes = (size_t)(s - buf) + 1u; + node->n_bytes = (size_t)(s - buf) + 1u; // Write integer part (right to left) do { @@ -358,16 +379,22 @@ serd_new_integer(int64_t i) return node; } -SerdNode +SerdNode* serd_new_blob(const void* buf, size_t size, 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->n_bytes = len; return node; } @@ -380,7 +407,7 @@ serd_node_type(const SerdNode* node) const char* serd_node_string(const SerdNode* node) { - return node->buf; + return (const char*)(node + 1); } size_t @@ -398,8 +425,5 @@ serd_node_flags(const SerdNode* node) void serd_node_free(SerdNode* node) { - if (node && node->buf) { - free((char*)node->buf); - node->buf = NULL; - } + free(node); } |