aboutsummaryrefslogtreecommitdiffstats
path: root/src/node.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-02-04 18:35:41 +0100
committerDavid Robillard <d@drobilla.net>2018-05-27 18:21:57 +0200
commitc564145e6f9aebabb5dfe0896e36d2bb6bc8b6b9 (patch)
tree7321decb1c1bc82935b87e6a733747a3976afeca /src/node.c
parentd37123707c7cde6368d6d368995628ad4809913c (diff)
downloadserd-c564145e6f9aebabb5dfe0896e36d2bb6bc8b6b9.tar.gz
serd-c564145e6f9aebabb5dfe0896e36d2bb6bc8b6b9.tar.bz2
serd-c564145e6f9aebabb5dfe0896e36d2bb6bc8b6b9.zip
Make nodes opaque
Diffstat (limited to 'src/node.c')
-rw-r--r--src/node.c168
1 files changed, 97 insertions, 71 deletions
diff --git a/src/node.c b/src/node.c
index 65a2172b..e7e18533 100644
--- a/src/node.c
+++ b/src/node.c
@@ -31,52 +31,79 @@
# 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);
}
+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;
+ }
+}
+
SERD_API
-SerdNode
-serd_node_from_string(SerdType type, const char* str)
+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;
}
SERD_API
-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;
}
SERD_API
-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;
}
@@ -84,12 +111,11 @@ SERD_API
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
@@ -119,7 +145,7 @@ string_sink(const void* buf, size_t len, void* stream)
}
SERD_API
-SerdNode
+SerdNode*
serd_node_new_uri_from_node(const SerdNode* uri_node,
const SerdURI* base,
SerdURI* out)
@@ -127,18 +153,18 @@ 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;
}
SERD_API
-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;
@@ -166,7 +192,7 @@ is_uri_path_char(const char c)
}
SERD_API
-SerdNode
+SerdNode*
serd_node_new_file_uri(const char* path,
const char* hostname,
SerdURI* out,
@@ -201,16 +227,18 @@ 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;
}
SERD_API
-SerdNode
+SerdNode*
serd_node_new_uri(const SerdURI* uri, const SerdURI* base, SerdURI* out)
{
SerdURI abs_uri = *uri;
@@ -219,23 +247,22 @@ 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;
}
SERD_API
-SerdNode
+SerdNode*
serd_node_new_relative_uri(const SerdURI* uri,
const SerdURI* base,
const SerdURI* root,
@@ -243,17 +270,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;
@@ -267,18 +293,19 @@ serd_digits(double abs)
}
SERD_API
-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;
@@ -294,13 +321,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;
@@ -309,7 +337,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) {
@@ -322,13 +350,13 @@ serd_node_new_decimal(double d, unsigned frac_digits)
}
SERD_API
-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;
@@ -337,7 +365,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 {
@@ -369,12 +397,12 @@ encode_chunk(uint8_t out[4], const uint8_t in[3], size_t n_in)
}
SERD_API
-SerdNode
+SerdNode*
serd_node_new_blob(const void* buf, size_t size, bool wrap_lines)
{
const size_t len = ((size + 2) / 3) * 4 + (wrap_lines ? (size / 57) : 0);
- uint8_t* str = (uint8_t*)calloc(1, len + 2);
- 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);
@@ -382,11 +410,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 + 1;
return node;
}
@@ -401,7 +430,7 @@ SERD_API
const char*
serd_node_get_string(const SerdNode* node)
{
- return node ? node->buf : NULL;
+ return node ? (const char*)(node + 1) : NULL;
}
SERD_API
@@ -422,8 +451,5 @@ SERD_API
void
serd_node_free(SerdNode* node)
{
- if (node && node->buf) {
- free((char*)node->buf);
- node->buf = NULL;
- }
+ free(node);
}