diff options
author | David Robillard <d@drobilla.net> | 2018-02-04 18:35:41 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2018-11-25 09:21:03 +0100 |
commit | 43e4cba8561d332cdc0fa9d257008dc68bb65a96 (patch) | |
tree | 7c4c773414bdda0e9c008e6c157f4bd88cd77cdf /src/node.c | |
parent | 7519da91b22e5c5898f522b897e1e77e7f0734b3 (diff) | |
download | serd-43e4cba8561d332cdc0fa9d257008dc68bb65a96.tar.gz serd-43e4cba8561d332cdc0fa9d257008dc68bb65a96.tar.bz2 serd-43e4cba8561d332cdc0fa9d257008dc68bb65a96.zip |
Make nodes opaque
Diffstat (limited to 'src/node.c')
-rw-r--r-- | src/node.c | 172 |
1 files changed, 101 insertions, 71 deletions
@@ -31,61 +31,87 @@ # endif #endif +SerdNode* +serd_node_malloc(size_t n_bytes, SerdNodeFlags flags, SerdType type) +{ + SerdNode* node = (SerdNode*)calloc(1, sizeof(SerdNode) + n_bytes + 1); + node->n_bytes = 0; + node->flags = flags; + node->type = type; + return node; +} + char* serd_node_buffer(SerdNode* node) { return (char*)(node + 1); } -SerdNode -serd_node_from_string(SerdType type, const char* str) +void +serd_node_set(SerdNode** dst, const SerdNode* src) +{ + 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) { + (*dst)->type = SERD_NOTHING; + } +} + +SerdNode* +serd_node_new_string(SerdType type, const char* str) { if (!str) { - return SERD_NODE_NULL; + return NULL; } - uint32_t flags = 0; - const size_t n_bytes = serd_strlen(str, &flags); - const SerdNode ret = { str, n_bytes, flags, type }; - return ret; + uint32_t 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; } -SerdNode -serd_node_from_substring(SerdType type, const char* str, const size_t len) +SerdNode* +serd_node_new_substring(SerdType type, const char* str, const size_t len) { if (!str) { - return SERD_NODE_NULL; + return NULL; } - uint32_t flags = 0; - const size_t n_bytes = serd_substrlen(str, len, &flags); - const SerdNode ret = { str, n_bytes, flags, type }; - return ret; + uint32_t 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; } 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((const char*)a->buf, - (const char*)b->buf, - a->n_bytes + 1))); + return (a == b) || + (a && b && a->type == b->type && a->n_bytes == b->n_bytes && + !memcmp(serd_node_get_string(a), + serd_node_get_string(b), + a->n_bytes)); } static size_t @@ -114,7 +140,7 @@ string_sink(const void* buf, size_t len, void* stream) return len; } -SerdNode +SerdNode* serd_node_new_uri_from_node(const SerdNode* uri_node, const SerdURI* base, SerdURI* out) @@ -122,17 +148,17 @@ serd_node_new_uri_from_node(const SerdNode* uri_node, const char* uri_str = serd_node_get_string(uri_node); return (uri_node->type == SERD_URI && uri_str) ? serd_node_new_uri_from_string(uri_str, base, out) - : SERD_NODE_NULL; + : NULL; } -SerdNode +SerdNode* serd_node_new_uri_from_string(const char* str, const SerdURI* base, SerdURI* out) { if (!str || str[0] == '\0') { // Empty URI => Base URI, or nothing if no base is given - return base ? serd_node_new_uri(base, NULL, out) : SERD_NODE_NULL; + return base ? serd_node_new_uri(base, NULL, out) : NULL; } SerdURI uri; @@ -159,7 +185,7 @@ is_uri_path_char(const char c) } } -SerdNode +SerdNode* serd_node_new_file_uri(const char* path, const char* hostname, SerdURI* out, @@ -194,15 +220,17 @@ serd_node_new_file_uri(const char* path, } serd_buffer_sink_finish(&buffer); + SerdNode* node = serd_node_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_node_new_uri(const SerdURI* uri, const SerdURI* base, SerdURI* out) { SerdURI abs_uri = *uri; @@ -211,22 +239,21 @@ serd_node_new_uri(const SerdURI* uri, const SerdURI* base, SerdURI* 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_node_new_relative_uri(const SerdURI* uri, const SerdURI* base, const SerdURI* root, @@ -234,17 +261,16 @@ serd_node_new_relative_uri(const SerdURI* 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; @@ -257,18 +283,19 @@ serd_digits(double abs) return lg < 1.0 ? 1U : (unsigned)lg; } -SerdNode +SerdNode* serd_node_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; @@ -284,13 +311,14 @@ serd_node_new_decimal(double d, unsigned frac_digits) *t-- = '0' + (dec % 10); } while ((dec /= 10) > 0); + *s++ = '.'; // Write fractional part (right to left) double frac_part = fabs(d - int_part); if (frac_part < DBL_EPSILON) { *s++ = '0'; - node.n_bytes = (s - buf); + node->n_bytes = (s - buf); } else { uint64_t frac = frac_part * pow(10.0, (int)frac_digits) + 0.5; s += frac_digits - 1; @@ -299,7 +327,7 @@ serd_node_new_decimal(double d, unsigned frac_digits) // Skip trailing zeros for (; i < frac_digits - 1 && !(frac % 10); ++i, --s, frac /= 10) {} - node.n_bytes = (s - buf) + 1; + node->n_bytes = (s - buf) + 1; // Write digits from last trailing zero to decimal point for (; i < frac_digits; ++i) { @@ -311,13 +339,13 @@ serd_node_new_decimal(double d, unsigned frac_digits) return node; } -SerdNode +SerdNode* serd_node_new_integer(int64_t i) { int64_t abs_i = (i < 0) ? -i : i; const unsigned digits = serd_digits(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; @@ -326,7 +354,7 @@ serd_node_new_integer(int64_t i) ++s; } - node.n_bytes = (s - buf) + 1; + node->n_bytes = (s - buf) + 1; // Write integer part (right to left) do { @@ -357,12 +385,16 @@ encode_chunk(uint8_t out[4], const uint8_t in[3], size_t n_in) out[3] = ((n_in > 2) ? b64_map[in[2] & 0x3F] : (uint8_t)'='); } -SerdNode +SerdNode* serd_node_new_blob(const void* buf, size_t size, bool wrap_lines) { + if (!buf || !size) { + return NULL; + } + const size_t len = (size + 2) / 3 * 4 + (wrap_lines * ((size - 1) / 57)); - 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); for (size_t i = 0, j = 0; i < size; i += 3, j += 4) { uint8_t in[4] = { 0, 0, 0, 0 }; size_t n_in = MIN(3, size - i); @@ -370,11 +402,12 @@ serd_node_new_blob(const void* buf, size_t size, bool wrap_lines) if (wrap_lines && i > 0 && (i % 57) == 0) { str[j++] = '\n'; - node.flags |= SERD_HAS_NEWLINE; + node->flags |= SERD_HAS_NEWLINE; } encode_chunk(str + j, in, n_in); } + node->n_bytes = len; return node; } @@ -387,7 +420,7 @@ serd_node_get_type(const SerdNode* node) const char* serd_node_get_string(const SerdNode* node) { - return node ? node->buf : NULL; + return node ? (const char*)(node + 1) : NULL; } size_t @@ -405,8 +438,5 @@ serd_node_get_flags(const SerdNode* node) void serd_node_free(SerdNode* node) { - if (node && node->buf) { - free((char*)node->buf); - node->buf = NULL; - } + free(node); } |