aboutsummaryrefslogtreecommitdiffstats
path: root/src/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/node.c')
-rw-r--r--src/node.c172
1 files changed, 98 insertions, 74 deletions
diff --git a/src/node.c b/src/node.c
index ee910725..b11625aa 100644
--- a/src/node.c
+++ b/src/node.c
@@ -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);
}