aboutsummaryrefslogtreecommitdiffstats
path: root/src/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/node.c')
-rw-r--r--src/node.c493
1 files changed, 256 insertions, 237 deletions
diff --git a/src/node.c b/src/node.c
index ab153b2b..6169895d 100644
--- a/src/node.c
+++ b/src/node.c
@@ -31,93 +31,93 @@
#include <string.h>
#ifdef _WIN32
-# ifndef isnan
-# define isnan(x) _isnan(x)
-# endif
-# ifndef isinf
-# define isinf(x) (!_finite(x))
-# endif
+# ifndef isnan
+# define isnan(x) _isnan(x)
+# endif
+# ifndef isinf
+# define isinf(x) (!_finite(x))
+# endif
#endif
SerdNode
serd_node_from_string(SerdType type, const uint8_t* str)
{
- if (!str) {
- return SERD_NODE_NULL;
- }
-
- SerdNodeFlags flags = 0;
- size_t buf_n_bytes = 0;
- const size_t buf_n_chars = serd_strlen(str, &buf_n_bytes, &flags);
- SerdNode ret = {str, buf_n_bytes, buf_n_chars, flags, type};
- return ret;
+ if (!str) {
+ return SERD_NODE_NULL;
+ }
+
+ SerdNodeFlags flags = 0;
+ size_t buf_n_bytes = 0;
+ const size_t buf_n_chars = serd_strlen(str, &buf_n_bytes, &flags);
+ SerdNode ret = {str, buf_n_bytes, buf_n_chars, flags, type};
+ return ret;
}
SerdNode
serd_node_from_substring(SerdType type, const uint8_t* str, const size_t len)
{
- if (!str) {
- return SERD_NODE_NULL;
- }
-
- SerdNodeFlags flags = 0;
- size_t buf_n_bytes = 0;
- const size_t buf_n_chars = serd_substrlen(str, len, &buf_n_bytes, &flags);
- assert(buf_n_bytes <= len);
- SerdNode ret = { str, buf_n_bytes, buf_n_chars, flags, type };
- return ret;
+ if (!str) {
+ return SERD_NODE_NULL;
+ }
+
+ SerdNodeFlags flags = 0;
+ size_t buf_n_bytes = 0;
+ const size_t buf_n_chars = serd_substrlen(str, len, &buf_n_bytes, &flags);
+ assert(buf_n_bytes <= len);
+ SerdNode ret = {str, buf_n_bytes, buf_n_chars, flags, type};
+ return ret;
}
SerdNode
serd_node_copy(const SerdNode* node)
{
- if (!node || !node->buf) {
- return SERD_NODE_NULL;
- }
-
- SerdNode copy = *node;
- uint8_t* buf = (uint8_t*)malloc(copy.n_bytes + 1);
- memcpy(buf, node->buf, copy.n_bytes + 1);
- copy.buf = buf;
- return copy;
+ if (!node || !node->buf) {
+ return SERD_NODE_NULL;
+ }
+
+ SerdNode copy = *node;
+ uint8_t* buf = (uint8_t*)malloc(copy.n_bytes + 1);
+ memcpy(buf, node->buf, copy.n_bytes + 1);
+ copy.buf = buf;
+ 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->n_chars == b->n_chars
- && ((a->buf == b->buf) || !memcmp((const char*)a->buf,
- (const char*)b->buf,
- a->n_bytes + 1)));
+ return (a == b) ||
+ (a->type == b->type && a->n_bytes == b->n_bytes &&
+ a->n_chars == b->n_chars &&
+ ((a->buf == b->buf) ||
+ !memcmp((const char*)a->buf, (const char*)b->buf, a->n_bytes + 1)));
}
static size_t
serd_uri_string_length(const SerdURI* uri)
{
- size_t len = uri->path_base.len;
+ size_t len = uri->path_base.len;
-#define ADD_LEN(field, n_delims) \
- if ((field).len) { len += (field).len + (n_delims); }
+#define ADD_LEN(field, n_delims) \
+ if ((field).len) { \
+ len += (field).len + (n_delims); \
+ }
- ADD_LEN(uri->path, 1) // + possible leading `/'
- ADD_LEN(uri->scheme, 1) // + trailing `:'
- ADD_LEN(uri->authority, 2) // + leading `//'
- ADD_LEN(uri->query, 1) // + leading `?'
- ADD_LEN(uri->fragment, 1) // + leading `#'
+ ADD_LEN(uri->path, 1) // + possible leading `/'
+ ADD_LEN(uri->scheme, 1) // + trailing `:'
+ ADD_LEN(uri->authority, 2) // + leading `//'
+ ADD_LEN(uri->query, 1) // + leading `?'
+ ADD_LEN(uri->fragment, 1) // + leading `#'
- return len + 2; // + 2 for authority `//'
+ return len + 2; // + 2 for authority `//'
}
static size_t
string_sink(const void* buf, size_t len, void* stream)
{
- uint8_t** ptr = (uint8_t**)stream;
- memcpy(*ptr, buf, len);
- *ptr += len;
- return len;
+ uint8_t** ptr = (uint8_t**)stream;
+ memcpy(*ptr, buf, len);
+ *ptr += len;
+ return len;
}
SerdNode
@@ -125,9 +125,9 @@ serd_node_new_uri_from_node(const SerdNode* uri_node,
const SerdURI* base,
SerdURI* out)
{
- return (uri_node->type == SERD_URI && uri_node->buf)
- ? serd_node_new_uri_from_string(uri_node->buf, base, out)
- : SERD_NODE_NULL;
+ return (uri_node->type == SERD_URI && uri_node->buf)
+ ? serd_node_new_uri_from_string(uri_node->buf, base, out)
+ : SERD_NODE_NULL;
}
SerdNode
@@ -135,33 +135,50 @@ serd_node_new_uri_from_string(const uint8_t* 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;
- }
-
- SerdURI uri;
- serd_uri_parse(str, &uri);
- return serd_node_new_uri(&uri, base, out); // Resolve/Serialise
+ 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;
+ }
+
+ SerdURI uri;
+ serd_uri_parse(str, &uri);
+ return serd_node_new_uri(&uri, base, out); // Resolve/Serialise
}
static inline bool
is_uri_path_char(const uint8_t c)
{
- if (is_alpha(c) || is_digit(c)) {
- return true;
- }
- switch (c) {
- case '-': case '.': case '_': case '~': // unreserved
- case ':': case '@': // pchar
- case '/': // separator
- // sub-delims
- case '!': case '$': case '&': case '\'': case '(': case ')':
- case '*': case '+': case ',': case ';': case '=':
- return true;
- default:
- return false;
- }
+ if (is_alpha(c) || is_digit(c)) {
+ return true;
+ }
+
+ switch (c) {
+ // unreserved:
+ case '-':
+ case '.':
+ case '_':
+ case '~':
+ // pchar:
+ case ':':
+ case '@':
+ // separator:
+ case '/':
+ // sub-delimeters:
+ case '!':
+ case '$':
+ case '&':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case ',':
+ case ';':
+ case '=':
+ return true;
+ default:
+ return false;
+ }
}
SerdNode
@@ -170,69 +187,69 @@ serd_node_new_file_uri(const uint8_t* path,
SerdURI* out,
bool escape)
{
- const size_t path_len = strlen((const char*)path);
- const size_t hostname_len = hostname ? strlen((const char*)hostname) : 0;
- const bool evil = is_windows_path(path);
- size_t uri_len = 0;
- uint8_t* uri = NULL;
-
- if (path[0] == '/' || is_windows_path(path)) {
- uri_len = strlen("file://") + hostname_len + evil;
- uri = (uint8_t*)malloc(uri_len + 1);
- snprintf((char*)uri, uri_len + 1, "file://%s%s",
- hostname ? (const char*)hostname : "",
- evil ? "/" : "");
- }
-
- SerdChunk chunk = { uri, uri_len };
- for (size_t i = 0; i < path_len; ++i) {
- if (evil && path[i] == '\\') {
- serd_chunk_sink("/", 1, &chunk);
- } else if (path[i] == '%') {
- serd_chunk_sink("%%", 2, &chunk);
- } else if (!escape || is_uri_path_char(path[i])) {
- serd_chunk_sink(path + i, 1, &chunk);
- } else {
- char escape_str[4] = { '%', 0, 0, 0 };
- snprintf(escape_str + 1,
- sizeof(escape_str) - 1,
- "%X",
- (unsigned)path[i]);
- serd_chunk_sink(escape_str, 3, &chunk);
- }
- }
- serd_chunk_sink_finish(&chunk);
-
- if (out) {
- serd_uri_parse(chunk.buf, out);
- }
-
- return serd_node_from_substring(SERD_URI, chunk.buf, chunk.len);
+ const size_t path_len = strlen((const char*)path);
+ const size_t hostname_len = hostname ? strlen((const char*)hostname) : 0;
+ const bool evil = is_windows_path(path);
+ size_t uri_len = 0;
+ uint8_t* uri = NULL;
+
+ if (path[0] == '/' || is_windows_path(path)) {
+ uri_len = strlen("file://") + hostname_len + evil;
+ uri = (uint8_t*)malloc(uri_len + 1);
+ snprintf((char*)uri,
+ uri_len + 1,
+ "file://%s%s",
+ hostname ? (const char*)hostname : "",
+ evil ? "/" : "");
+ }
+
+ SerdChunk chunk = {uri, uri_len};
+ for (size_t i = 0; i < path_len; ++i) {
+ if (evil && path[i] == '\\') {
+ serd_chunk_sink("/", 1, &chunk);
+ } else if (path[i] == '%') {
+ serd_chunk_sink("%%", 2, &chunk);
+ } else if (!escape || is_uri_path_char(path[i])) {
+ serd_chunk_sink(path + i, 1, &chunk);
+ } else {
+ char escape_str[4] = {'%', 0, 0, 0};
+ snprintf(escape_str + 1, sizeof(escape_str) - 1, "%X", (unsigned)path[i]);
+ serd_chunk_sink(escape_str, 3, &chunk);
+ }
+ }
+
+ serd_chunk_sink_finish(&chunk);
+
+ if (out) {
+ serd_uri_parse(chunk.buf, out);
+ }
+
+ return serd_node_from_substring(SERD_URI, chunk.buf, chunk.len);
}
SerdNode
serd_node_new_uri(const SerdURI* uri, const SerdURI* base, SerdURI* out)
{
- SerdURI abs_uri = *uri;
- if (base) {
- serd_uri_resolve(uri, base, &abs_uri);
- }
-
- const size_t len = serd_uri_string_length(&abs_uri);
- uint8_t* buf = (uint8_t*)malloc(len + 1);
- SerdNode node = { buf, 0, 0, 0, SERD_URI };
- uint8_t* ptr = buf;
- const size_t actual_len = serd_uri_serialise(&abs_uri, string_sink, &ptr);
-
- buf[actual_len] = '\0';
- node.n_bytes = actual_len;
- node.n_chars = serd_strlen(buf, NULL, NULL);
-
- if (out) {
- serd_uri_parse(buf, out); // TODO: cleverly avoid double parse
- }
-
- return node;
+ SerdURI abs_uri = *uri;
+ if (base) {
+ serd_uri_resolve(uri, base, &abs_uri);
+ }
+
+ const size_t len = serd_uri_string_length(&abs_uri);
+ uint8_t* buf = (uint8_t*)malloc(len + 1);
+ SerdNode node = {buf, 0, 0, 0, SERD_URI};
+ uint8_t* ptr = buf;
+ const size_t actual_len = serd_uri_serialise(&abs_uri, string_sink, &ptr);
+
+ buf[actual_len] = '\0';
+ node.n_bytes = actual_len;
+ node.n_chars = serd_strlen(buf, NULL, NULL);
+
+ if (out) {
+ serd_uri_parse(buf, out); // TODO: cleverly avoid double parse
+ }
+
+ return node;
}
SerdNode
@@ -241,129 +258,131 @@ serd_node_new_relative_uri(const SerdURI* uri,
const SerdURI* root,
SerdURI* out)
{
- const size_t uri_len = serd_uri_string_length(uri);
- const size_t base_len = serd_uri_string_length(base);
- uint8_t* buf = (uint8_t*)malloc(uri_len + base_len + 1);
- SerdNode node = { buf, 0, 0, 0, SERD_URI };
- uint8_t* ptr = buf;
- const size_t actual_len = serd_uri_serialise_relative(
- uri, base, root, string_sink, &ptr);
-
- buf[actual_len] = '\0';
- node.n_bytes = actual_len;
- node.n_chars = serd_strlen(buf, NULL, NULL);
-
- if (out) {
- serd_uri_parse(buf, out); // TODO: cleverly avoid double parse
- }
-
- return node;
+ const size_t uri_len = serd_uri_string_length(uri);
+ const size_t base_len = serd_uri_string_length(base);
+ uint8_t* buf = (uint8_t*)malloc(uri_len + base_len + 1);
+ SerdNode node = {buf, 0, 0, 0, SERD_URI};
+ uint8_t* ptr = buf;
+ const size_t actual_len =
+ serd_uri_serialise_relative(uri, base, root, string_sink, &ptr);
+
+ buf[actual_len] = '\0';
+ node.n_bytes = actual_len;
+ node.n_chars = serd_strlen(buf, NULL, NULL);
+
+ if (out) {
+ serd_uri_parse(buf, out); // TODO: cleverly avoid double parse
+ }
+
+ return node;
}
static inline unsigned
serd_digits(double abs)
{
- const double lg = ceil(log10(floor(abs) + 1.0));
- return lg < 1.0 ? 1U : (unsigned)lg;
+ const double lg = ceil(log10(floor(abs) + 1.0));
+ return lg < 1.0 ? 1U : (unsigned)lg;
}
SerdNode
serd_node_new_decimal(double d, unsigned frac_digits)
{
- if (isnan(d) || isinf(d)) {
- return SERD_NODE_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 = { (const uint8_t*)buf, 0, 0, 0, SERD_LITERAL };
- const double int_part = floor(abs_d);
-
- // Point s to decimal point location
- char* s = buf + int_digits;
- if (d < 0.0) {
- *buf = '-';
- ++s;
- }
-
- // Write integer part (right to left)
- char* t = s - 1;
- uint64_t dec = (uint64_t)int_part;
- do {
- *t-- = (char)('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 = node.n_chars = (size_t)(s - buf);
- } else {
- uint64_t frac = (uint64_t)llround(frac_part * pow(10.0, (int)frac_digits));
- s += frac_digits - 1;
- unsigned i = 0;
-
- // Skip trailing zeros
- for (; i < frac_digits - 1 && !(frac % 10); ++i, --s, frac /= 10) {}
-
- node.n_bytes = node.n_chars = (size_t)(s - buf) + 1u;
-
- // Write digits from last trailing zero to decimal point
- for (; i < frac_digits; ++i) {
- *s-- = (char)('0' + (frac % 10));
- frac /= 10;
- }
- }
-
- return node;
+ if (isnan(d) || isinf(d)) {
+ return SERD_NODE_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 = {(const uint8_t*)buf, 0, 0, 0, SERD_LITERAL};
+ const double int_part = floor(abs_d);
+
+ // Point s to decimal point location
+ char* s = buf + int_digits;
+ if (d < 0.0) {
+ *buf = '-';
+ ++s;
+ }
+
+ // Write integer part (right to left)
+ char* t = s - 1;
+ uint64_t dec = (uint64_t)int_part;
+ do {
+ *t-- = (char)('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 = node.n_chars = (size_t)(s - buf);
+ } else {
+ uint64_t frac = (uint64_t)llround(frac_part * pow(10.0, (int)frac_digits));
+ s += frac_digits - 1;
+ unsigned i = 0;
+
+ // Skip trailing zeros
+ for (; i < frac_digits - 1 && !(frac % 10); ++i, --s, frac /= 10) {
+ }
+
+ node.n_bytes = node.n_chars = (size_t)(s - buf) + 1u;
+
+ // Write digits from last trailing zero to decimal point
+ for (; i < frac_digits; ++i) {
+ *s-- = (char)('0' + (frac % 10));
+ frac /= 10;
+ }
+ }
+
+ return node;
}
SerdNode
serd_node_new_integer(int64_t i)
{
- int64_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 uint8_t*)buf, 0, 0, 0, SERD_LITERAL };
-
- // Point s to the end
- char* s = buf + digits - 1;
- if (i < 0) {
- *buf = '-';
- ++s;
- }
-
- node.n_bytes = node.n_chars = (size_t)(s - buf) + 1u;
-
- // Write integer part (right to left)
- do {
- *s-- = (char)('0' + (abs_i % 10));
- } while ((abs_i /= 10) > 0);
-
- return node;
+ int64_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 uint8_t*)buf, 0, 0, 0, SERD_LITERAL};
+
+ // Point s to the end
+ char* s = buf + digits - 1;
+ if (i < 0) {
+ *buf = '-';
+ ++s;
+ }
+
+ node.n_bytes = node.n_chars = (size_t)(s - buf) + 1u;
+
+ // Write integer part (right to left)
+ do {
+ *s-- = (char)('0' + (abs_i % 10));
+ } while ((abs_i /= 10) > 0);
+
+ return node;
}
SerdNode
serd_node_new_blob(const void* buf, size_t size, bool wrap_lines)
{
- const size_t len = serd_base64_get_length(size, wrap_lines);
- uint8_t* str = (uint8_t*)calloc(len + 2, 1);
- SerdNode node = { str, len, len, 0, SERD_LITERAL };
-
- if (serd_base64_encode(str, buf, size, wrap_lines)) {
- node.flags |= SERD_HAS_NEWLINE;
- }
- return node;
+ const size_t len = serd_base64_get_length(size, wrap_lines);
+ uint8_t* str = (uint8_t*)calloc(len + 2, 1);
+ SerdNode node = {str, len, len, 0, SERD_LITERAL};
+
+ if (serd_base64_encode(str, buf, size, wrap_lines)) {
+ node.flags |= SERD_HAS_NEWLINE;
+ }
+
+ return node;
}
void
serd_node_free(SerdNode* node)
{
- if (node && node->buf) {
- free((uint8_t*)node->buf);
- node->buf = NULL;
- }
+ if (node && node->buf) {
+ free((uint8_t*)node->buf);
+ node->buf = NULL;
+ }
}