aboutsummaryrefslogtreecommitdiffstats
path: root/src/node.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-02-04 15:33:36 +0100
committerDavid Robillard <d@drobilla.net>2022-01-13 15:33:54 -0500
commitcda46ec67d41fb120809d5d1d16c05eb1b3882da (patch)
treea968e71f84289c3ce96b654e9bc285812c17f7d4 /src/node.c
parenta650d2ad2d4785c40405854740e70f487ae1016a (diff)
downloadserd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.tar.gz
serd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.tar.bz2
serd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.zip
Make nodes opaque
Diffstat (limited to 'src/node.c')
-rw-r--r--src/node.c180
1 files changed, 104 insertions, 76 deletions
diff --git a/src/node.c b/src/node.c
index 869d9bfc..ff3f3f71 100644
--- a/src/node.c
+++ b/src/node.c
@@ -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);
}