diff options
author | David Robillard <d@drobilla.net> | 2018-02-04 15:33:36 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2022-01-13 15:33:54 -0500 |
commit | cda46ec67d41fb120809d5d1d16c05eb1b3882da (patch) | |
tree | a968e71f84289c3ce96b654e9bc285812c17f7d4 /src | |
parent | a650d2ad2d4785c40405854740e70f487ae1016a (diff) | |
download | serd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.tar.gz serd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.tar.bz2 serd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.zip |
Make nodes opaque
Diffstat (limited to 'src')
-rw-r--r-- | src/base64.h | 3 | ||||
-rw-r--r-- | src/byte_source.h | 3 | ||||
-rw-r--r-- | src/env.c | 124 | ||||
-rw-r--r-- | src/n3.c | 35 | ||||
-rw-r--r-- | src/node.c | 180 | ||||
-rw-r--r-- | src/node.h | 8 | ||||
-rw-r--r-- | src/reader.c | 41 | ||||
-rw-r--r-- | src/reader.h | 12 | ||||
-rw-r--r-- | src/serdi.c | 14 | ||||
-rw-r--r-- | src/uri_utils.h | 9 | ||||
-rw-r--r-- | src/writer.c | 229 |
11 files changed, 356 insertions, 302 deletions
diff --git a/src/base64.h b/src/base64.h index 8ff6acc4..6fbe6c5c 100644 --- a/src/base64.h +++ b/src/base64.h @@ -30,7 +30,8 @@ @param wrap_lines Wrap lines at 76 characters to conform to RFC 2045. @return The length of the base64 encoding, excluding null terminator. */ -SERD_CONST_FUNC size_t +SERD_CONST_FUNC +size_t serd_base64_get_length(size_t size, bool wrap_lines); /** diff --git a/src/byte_source.h b/src/byte_source.h index 7a42feaa..63cc1b51 100644 --- a/src/byte_source.h +++ b/src/byte_source.h @@ -70,7 +70,8 @@ serd_byte_source_prepare(SerdByteSource* source); SerdStatus serd_byte_source_page(SerdByteSource* source); -static inline SERD_PURE_FUNC uint8_t +SERD_PURE_FUNC +static inline uint8_t serd_byte_source_peek(SerdByteSource* source) { assert(source->prepared); @@ -14,6 +14,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "node.h" + #include "serd/serd.h" #include <stdbool.h> @@ -22,14 +24,14 @@ #include <string.h> typedef struct { - SerdNode name; - SerdNode uri; + SerdNode* name; + SerdNode* uri; } SerdPrefix; struct SerdEnvImpl { SerdPrefix* prefixes; size_t n_prefixes; - SerdNode base_uri_node; + SerdNode* base_uri_node; SerdURIView base_uri; }; @@ -52,12 +54,11 @@ serd_env_free(SerdEnv* const env) } for (size_t i = 0; i < env->n_prefixes; ++i) { - serd_node_free(&env->prefixes[i].name); - serd_node_free(&env->prefixes[i].uri); + serd_node_free(env->prefixes[i].name); + serd_node_free(env->prefixes[i].uri); } - free(env->prefixes); - serd_node_free(&env->base_uri_node); + serd_node_free(env->base_uri_node); free(env); } @@ -68,7 +69,7 @@ serd_env_base_uri(const SerdEnv* const env, SerdURIView* const out) *out = env->base_uri; } - return &env->base_uri_node; + return env->base_uri_node; } SerdStatus @@ -78,40 +79,40 @@ serd_env_set_base_uri(SerdEnv* const env, const SerdNode* const uri) return SERD_ERR_BAD_ARG; } - if (!uri || !uri->buf) { - serd_node_free(&env->base_uri_node); - env->base_uri_node = SERD_NODE_NULL; + if (!uri) { + serd_node_free(env->base_uri_node); + env->base_uri_node = NULL; env->base_uri = SERD_URI_NULL; return SERD_SUCCESS; } // Resolve base URI and create a new node and URI for it SerdURIView base_uri; - SerdNode base_uri_node = + SerdNode* base_uri_node = serd_new_uri_from_node(uri, &env->base_uri, &base_uri); // Replace the current base URI - serd_node_free(&env->base_uri_node); + serd_node_free(env->base_uri_node); env->base_uri_node = base_uri_node; env->base_uri = base_uri; return SERD_SUCCESS; } -SERD_PURE_FUNC static SerdPrefix* +SERD_PURE_FUNC +static SerdPrefix* serd_env_find(const SerdEnv* const env, const char* const name, const size_t name_len) { for (size_t i = 0; i < env->n_prefixes; ++i) { - const SerdNode* const prefix_name = &env->prefixes[i].name; - if (prefix_name->n_bytes == name_len) { - if (!memcmp(prefix_name->buf, name, name_len)) { + const SerdNode* const prefix_name = env->prefixes[i].name; + if (prefix_name->length == name_len) { + if (!memcmp(serd_node_string(prefix_name), name, name_len)) { return &env->prefixes[i]; } } } - return NULL; } @@ -120,12 +121,13 @@ serd_env_add(SerdEnv* const env, const SerdNode* const name, const SerdNode* const uri) { - SerdPrefix* const prefix = serd_env_find(env, name->buf, name->n_bytes); + const char* name_str = serd_node_string(name); + SerdPrefix* const prefix = serd_env_find(env, name_str, name->length); if (prefix) { - if (!serd_node_equals(&prefix->uri, uri)) { - SerdNode old_prefix_uri = prefix->uri; - prefix->uri = serd_node_copy(uri); - serd_node_free(&old_prefix_uri); + if (!serd_node_equals(prefix->uri, uri)) { + SerdNode* old_prefix_uri = prefix->uri; + prefix->uri = serd_node_copy(uri); + serd_node_free(old_prefix_uri); } } else { env->prefixes = (SerdPrefix*)realloc( @@ -140,22 +142,22 @@ serd_env_set_prefix(SerdEnv* const env, const SerdNode* const name, const SerdNode* const uri) { - if (!name->buf || uri->type != SERD_URI) { + if (!name || uri->type != SERD_URI) { return SERD_ERR_BAD_ARG; } - if (serd_uri_string_has_scheme(uri->buf)) { + if (serd_uri_string_has_scheme(serd_node_string(uri))) { // Set prefix to absolute URI serd_env_add(env, name, uri); } else { // Resolve relative URI and create a new node and URI for it SerdURIView abs_uri; - SerdNode abs_uri_node = + SerdNode* abs_uri_node = serd_new_uri_from_node(uri, &env->base_uri, &abs_uri); // Set prefix to resolved (absolute) URI - serd_env_add(env, name, &abs_uri_node); - serd_node_free(&abs_uri_node); + serd_env_add(env, name, abs_uri_node); + serd_node_free(abs_uri_node); } return SERD_SUCCESS; @@ -166,29 +168,36 @@ serd_env_set_prefix_from_strings(SerdEnv* const env, const char* const name, const char* const uri) { - const SerdNode name_node = serd_node_from_string(SERD_LITERAL, name); - const SerdNode uri_node = serd_node_from_string(SERD_URI, uri); + SerdNode* name_node = serd_new_string(SERD_LITERAL, name); + SerdNode* uri_node = serd_new_string(SERD_URI, uri); + + const SerdStatus st = serd_env_set_prefix(env, name_node, uri_node); - return serd_env_set_prefix(env, &name_node, &uri_node); + serd_node_free(name_node); + serd_node_free(uri_node); + return st; } bool -serd_env_qualify(const SerdEnv* const env, - const SerdNode* const uri, - SerdNode* const prefix, - SerdStringView* const suffix) +serd_env_qualify(const SerdEnv* const env, + const SerdNode* const uri, + const SerdNode** const prefix, + SerdStringView* const suffix) { if (!env) { return false; } for (size_t i = 0; i < env->n_prefixes; ++i) { - const SerdNode* const prefix_uri = &env->prefixes[i].uri; - if (uri->n_bytes >= prefix_uri->n_bytes) { - if (!strncmp(uri->buf, prefix_uri->buf, prefix_uri->n_bytes)) { + const SerdNode* const prefix_uri = env->prefixes[i].uri; + if (uri->length >= prefix_uri->length) { + const char* prefix_str = serd_node_string(prefix_uri); + const char* uri_str = serd_node_string(uri); + + if (!strncmp(uri_str, prefix_str, prefix_uri->length)) { *prefix = env->prefixes[i].name; - suffix->buf = uri->buf + prefix_uri->n_bytes; - suffix->len = uri->n_bytes - prefix_uri->n_bytes; + suffix->buf = uri_str + prefix_uri->length; + suffix->len = uri->length - prefix_uri->length; return true; } } @@ -202,37 +211,36 @@ serd_env_expand(const SerdEnv* const env, SerdStringView* const uri_prefix, SerdStringView* const uri_suffix) { - if (!env) { + if (!env || !curie) { return SERD_ERR_BAD_CURIE; } - const char* const colon = - (const char*)memchr(curie->buf, ':', curie->n_bytes + 1); + const char* const str = serd_node_string(curie); + const char* const colon = (const char*)memchr(str, ':', curie->length + 1); if (curie->type != SERD_CURIE || !colon) { return SERD_ERR_BAD_ARG; } - const size_t name_len = (size_t)(colon - curie->buf); - const SerdPrefix* const prefix = serd_env_find(env, curie->buf, name_len); + const size_t name_len = (size_t)(colon - str); + const SerdPrefix* const prefix = serd_env_find(env, str, name_len); if (prefix) { - uri_prefix->buf = prefix->uri.buf; - uri_prefix->len = prefix->uri.n_bytes; + uri_prefix->buf = serd_node_string(prefix->uri); + uri_prefix->len = prefix->uri ? prefix->uri->length : 0; uri_suffix->buf = colon + 1; - uri_suffix->len = curie->n_bytes - name_len - 1; + uri_suffix->len = curie->length - name_len - 1; return SERD_SUCCESS; } return SERD_ERR_BAD_CURIE; } -SerdNode +SerdNode* serd_env_expand_node(const SerdEnv* const env, const SerdNode* const node) { if (!env) { - return SERD_NODE_NULL; + return NULL; } switch (node->type) { - case SERD_NOTHING: case SERD_LITERAL: break; case SERD_URI: { @@ -243,18 +251,20 @@ serd_env_expand_node(const SerdEnv* const env, const SerdNode* const node) SerdStringView prefix; SerdStringView suffix; if (serd_env_expand(env, node, &prefix, &suffix)) { - return SERD_NODE_NULL; + return NULL; } const size_t len = prefix.len + suffix.len; - char* buf = (char*)malloc(len + 1); - SerdNode ret = {buf, len, 0, SERD_URI}; - snprintf(buf, ret.n_bytes + 1, "%s%s", prefix.buf, suffix.buf); + SerdNode* ret = serd_node_malloc(len, 0, SERD_URI); + char* buf = serd_node_buffer(ret); + + snprintf(buf, len + 1, "%s%s", prefix.buf, suffix.buf); + ret->length = len; return ret; } case SERD_BLANK: break; } - return SERD_NODE_NULL; + return NULL; } void @@ -263,6 +273,6 @@ serd_env_foreach(const SerdEnv* const env, void* const handle) { for (size_t i = 0; i < env->n_prefixes; ++i) { - func(handle, &env->prefixes[i].name, &env->prefixes[i].uri); + func(handle, env->prefixes[i].name, env->prefixes[i].uri); } } @@ -15,6 +15,7 @@ */ #include "byte_source.h" +#include "node.h" #include "reader.h" #include "serd_internal.h" #include "stack.h" @@ -633,7 +634,7 @@ read_PN_LOCAL(SerdReader* const reader, const Ref dest, bool* const ate_dot) SerdNode* const n = deref(reader, dest); if (trailing_unescaped_dot) { // Ate trailing dot, pop it from stack/node and inform caller - --n->n_bytes; + --n->length; serd_stack_pop(&reader->stack, 1); *ate_dot = true; } @@ -655,7 +656,8 @@ read_PN_PREFIX_tail(SerdReader* const reader, const Ref dest) } const SerdNode* const n = deref(reader, dest); - if (n->buf[n->n_bytes - 1] == '.' && read_PN_CHARS(reader, dest)) { + if (serd_node_string(n)[serd_node_length(n) - 1] == '.' && + read_PN_CHARS(reader, dest)) { return r_err(reader, SERD_ERR_BAD_SYNTAX, "prefix ends with `.'\n"); } @@ -986,8 +988,8 @@ read_verb(SerdReader* const reader, Ref* const dest) bool ate_dot = false; SerdNode* node = deref(reader, *dest); const int next = peek_byte(reader); - if (!st && node->n_bytes == 1 && node->buf[0] == 'a' && next != ':' && - !is_PN_CHARS_BASE((uint32_t)next)) { + if (!st && node->length == 1 && serd_node_string(node)[0] == 'a' && + next != ':' && !is_PN_CHARS_BASE((uint32_t)next)) { pop_node(reader, *dest); *dest = push_node(reader, SERD_URI, NS_RDF "type", 47); return SERD_SUCCESS; @@ -1031,20 +1033,21 @@ read_BLANK_NODE_LABEL(SerdReader* const reader, } } - SerdNode* n = deref(reader, ref); - if (n->buf[n->n_bytes - 1] == '.' && read_PN_CHARS(reader, ref)) { + SerdNode* n = deref(reader, ref); + char* buf = serd_node_buffer(n); + if (buf[n->length - 1] == '.' && read_PN_CHARS(reader, ref)) { // Ate trailing dot, pop it from stack/node and inform caller - --n->n_bytes; + --n->length; serd_stack_pop(&reader->stack, 1); *ate_dot = true; } if (fancy_syntax(reader)) { - if (is_digit(n->buf[reader->bprefix_len + 1])) { - if ((n->buf[reader->bprefix_len]) == 'b') { - ((char*)n->buf)[reader->bprefix_len] = 'B'; // Prevent clash - reader->seen_genid = true; - } else if (reader->seen_genid && n->buf[reader->bprefix_len] == 'B') { + if (is_digit(buf[reader->bprefix_len + 1])) { + if ((buf[reader->bprefix_len]) == 'b') { + buf[reader->bprefix_len] = 'B'; // Prevent clash + reader->seen_genid = true; + } else if (reader->seen_genid && buf[reader->bprefix_len] == 'B') { *dest = pop_node(reader, *dest); return r_err(reader, SERD_ERR_ID_CLASH, @@ -1186,8 +1189,8 @@ read_object(SerdReader* const reader, while (!read_PN_CHARS_BASE(reader, o)) { } node = deref(reader, o); - if ((node->n_bytes == 4 && !memcmp(node->buf, "true", 4)) || - (node->n_bytes == 5 && !memcmp(node->buf, "false", 5))) { + if ((node->length == 4 && !memcmp(serd_node_string(node), "true", 4)) || + (node->length == 5 && !memcmp(serd_node_string(node), "false", 5))) { node->type = SERD_LITERAL; datatype = push_node(reader, SERD_URI, XSD_BOOLEAN, XSD_BOOLEAN_LEN); ret = SERD_SUCCESS; @@ -1573,11 +1576,11 @@ tokcmp(SerdReader* const reader, const size_t n) { SerdNode* node = deref(reader, ref); - if (!node || node->n_bytes != n) { + if (!node || node->length != n) { return -1; } - return serd_strncasecmp(node->buf, tok, n); + return serd_strncasecmp(serd_node_string(node), tok, n); } SerdStatus @@ -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); } @@ -22,9 +22,9 @@ #include <stddef.h> struct SerdNodeImpl { - size_t n_bytes; /**< Size in bytes (not including null) */ - SerdNodeFlags flags; /**< Node flags (e.g. string properties) */ - SerdNodeType type; /**< Node type */ + size_t length; ///< Length in bytes (not including null) + SerdNodeFlags flags; ///< Node flags + SerdNodeType type; ///< Node type }; static inline char* @@ -40,7 +40,7 @@ serd_node_buffer_c(const SerdNode* node) } SerdNode* -serd_node_malloc(size_t n_bytes, SerdNodeFlags flags, SerdNodeType type); +serd_node_malloc(size_t length, SerdNodeFlags flags, SerdNodeType type); void serd_node_set(SerdNode** dst, const SerdNode* src); diff --git a/src/reader.c b/src/reader.c index cc30c86e..86df3134 100644 --- a/src/reader.c +++ b/src/reader.c @@ -17,6 +17,7 @@ #include "reader.h" #include "byte_source.h" +#include "node.h" #include "stack.h" #include "system.h" @@ -45,9 +46,11 @@ void set_blank_id(SerdReader* const reader, const Ref ref, const size_t buf_size) { SerdNode* node = deref(reader, ref); + char* buf = (char*)(node + 1); const char* prefix = reader->bprefix ? (const char*)reader->bprefix : ""; - node->n_bytes = (size_t)snprintf( - (char*)node->buf, buf_size, "%sb%u", prefix, reader->next_id++); + + node->length = + (size_t)snprintf(buf, buf_size, "%sb%u", prefix, reader->next_id++); } size_t @@ -88,19 +91,19 @@ push_node_padded(SerdReader* const reader, const size_t maxlen, const SerdNodeType type, const char* const str, - const size_t n_bytes) + const size_t length) { void* mem = serd_stack_push_aligned( &reader->stack, sizeof(SerdNode) + maxlen + 1, sizeof(SerdNode)); SerdNode* const node = (SerdNode*)mem; - node->n_bytes = n_bytes; - node->flags = 0; - node->type = type; - node->buf = NULL; + + node->length = length; + node->flags = 0; + node->type = type; char* buf = (char*)(node + 1); - memcpy(buf, str, n_bytes + 1); + memcpy(buf, str, length + 1); #ifdef SERD_STACK_CHECK reader->allocs = (Ref*)realloc(reader->allocs, @@ -114,20 +117,16 @@ Ref push_node(SerdReader* const reader, const SerdNodeType type, const char* const str, - const size_t n_bytes) + const size_t length) { - return push_node_padded(reader, n_bytes, type, str, n_bytes); + return push_node_padded(reader, length, type, str, length); } +SERD_PURE_FUNC SerdNode* deref(SerdReader* const reader, const Ref ref) { - if (ref) { - SerdNode* node = (SerdNode*)(reader->stack.buf + ref); - node->buf = (char*)node + sizeof(SerdNode); - return node; - } - return NULL; + return ref ? (SerdNode*)(reader->stack.buf + ref) : NULL; } Ref @@ -154,8 +153,8 @@ emit_statement(SerdReader* const reader, const Ref l) { SerdNode* graph = deref(reader, ctx.graph); - if (!graph && reader->default_graph.buf) { - graph = &reader->default_graph; + if (!graph && reader->default_graph) { + graph = reader->default_graph; } const SerdStatus st = !reader->statement_func @@ -202,7 +201,7 @@ serd_reader_new(const SerdSyntax syntax, me->prefix_func = prefix_func; me->statement_func = statement_func; me->end_func = end_func; - me->default_graph = SERD_NODE_NULL; + me->default_graph = NULL; me->stack = serd_stack_new(SERD_PAGE_SIZE); me->syntax = syntax; me->next_id = 1; @@ -240,7 +239,7 @@ serd_reader_free(SerdReader* const reader) pop_node(reader, reader->rdf_nil); pop_node(reader, reader->rdf_rest); pop_node(reader, reader->rdf_first); - serd_node_free(&reader->default_graph); + serd_node_free(reader->default_graph); #ifdef SERD_STACK_CHECK free(reader->allocs); @@ -278,7 +277,7 @@ void serd_reader_set_default_graph(SerdReader* const reader, const SerdNode* const graph) { - serd_node_free(&reader->default_graph); + serd_node_free(reader->default_graph); reader->default_graph = serd_node_copy(graph); } diff --git a/src/reader.h b/src/reader.h index ae248410..bb8f0b30 100644 --- a/src/reader.h +++ b/src/reader.h @@ -18,6 +18,7 @@ #define SERD_READER_H #include "byte_source.h" +#include "node.h" #include "stack.h" #include "serd/serd.h" @@ -67,7 +68,7 @@ struct SerdReaderImpl { Ref rdf_first; Ref rdf_rest; Ref rdf_nil; - SerdNode default_graph; + SerdNode* default_graph; SerdByteSource source; SerdStack stack; SerdSyntax syntax; @@ -92,15 +93,16 @@ push_node_padded(SerdReader* reader, size_t maxlen, SerdNodeType type, const char* str, - size_t n_bytes); + size_t length); Ref push_node(SerdReader* reader, SerdNodeType type, const char* str, - size_t n_bytes); + size_t length); -SERD_PURE_FUNC size_t +SERD_PURE_FUNC +size_t genid_size(const SerdReader* reader); Ref @@ -181,7 +183,7 @@ push_byte(SerdReader* reader, Ref ref, const int c) *(uint8_t*)(s - 1) = (uint8_t)c; *s = '\0'; - ++node->n_bytes; + ++node->length; return SERD_SUCCESS; } diff --git a/src/serdi.c b/src/serdi.c index c447e2b2..babe4575 100644 --- a/src/serdi.c +++ b/src/serdi.c @@ -65,7 +65,8 @@ get_syntax(const char* const name) return (SerdSyntax)0; } -static SERD_PURE_FUNC SerdSyntax +static SERD_PURE_FUNC +SerdSyntax guess_syntax(const char* const filename) { const char* ext = strrchr(filename, '.'); @@ -316,7 +317,7 @@ main(int argc, char** argv) choose_style(input_syntax, output_syntax, ascii, bulk_write, full_uris); SerdURIView base_uri = SERD_URI_NULL; - SerdNode base = SERD_NODE_NULL; + SerdNode* base = NULL; if (a < argc) { // Base URI given on command line base = serd_new_uri_from_string((const char*)argv[a], NULL, &base_uri); } else if (from_file && in_fd != stdin) { // Use input file URI @@ -324,7 +325,7 @@ main(int argc, char** argv) } FILE* const out_fd = stdout; - SerdEnv* const env = serd_env_new(&base); + SerdEnv* const env = serd_env_new(base); SerdWriter* const writer = serd_writer_new( output_syntax, writer_flags, env, &base_uri, serd_file_sink, out_fd); @@ -344,10 +345,11 @@ main(int argc, char** argv) serd_writer_set_error_sink(writer, quiet_error_sink, NULL); } - SerdNode root = serd_node_from_string(SERD_URI, root_uri); - serd_writer_set_root_uri(writer, &root); + SerdNode* root = root_uri ? serd_new_string(SERD_URI, root_uri) : NULL; + serd_writer_set_root_uri(writer, root); serd_writer_chop_blank_prefix(writer, chop_prefix); serd_reader_add_blank_prefix(reader, add_prefix); + serd_node_free(root); SerdStatus st = SERD_SUCCESS; if (!from_file) { @@ -366,7 +368,7 @@ main(int argc, char** argv) serd_writer_finish(writer); serd_writer_free(writer); serd_env_free(env); - serd_node_free(&base); + serd_node_free(base); free(input_path); if (from_file) { diff --git a/src/uri_utils.h b/src/uri_utils.h index 03d397d2..6b07ec48 100644 --- a/src/uri_utils.h +++ b/src/uri_utils.h @@ -50,7 +50,8 @@ uri_path_at(const SerdURIView* uri, size_t i) Return the index of the first differing character after the last root slash, or zero if `uri` is not under `root`. */ -static inline SERD_PURE_FUNC size_t +static inline SERD_PURE_FUNC +size_t uri_rooted_index(const SerdURIView* uri, const SerdURIView* root) { if (!root || !root->scheme.len || @@ -80,14 +81,16 @@ uri_rooted_index(const SerdURIView* uri, const SerdURIView* root) } /** Return true iff `uri` shares path components with `root` */ -static inline SERD_PURE_FUNC bool +static inline SERD_PURE_FUNC +bool uri_is_related(const SerdURIView* uri, const SerdURIView* root) { return uri_rooted_index(uri, root) > 0; } /** Return true iff `uri` is within the base of `root` */ -static inline SERD_PURE_FUNC bool +static inline SERD_PURE_FUNC +bool uri_is_under(const SerdURIView* uri, const SerdURIView* root) { const size_t index = uri_rooted_index(uri, root); diff --git a/src/writer.c b/src/writer.c index 579c7f3e..abfe327b 100644 --- a/src/writer.c +++ b/src/writer.c @@ -15,6 +15,7 @@ */ #include "byte_sink.h" +#include "node.h" #include "serd_internal.h" #include "stack.h" #include "string_utils.h" @@ -39,14 +40,12 @@ typedef enum { } Field; typedef struct { - SerdNode graph; - SerdNode subject; - SerdNode predicate; + SerdNode* graph; + SerdNode* subject; + SerdNode* predicate; } WriteContext; -static const WriteContext WRITE_CONTEXT_NULL = {{0, 0, 0, SERD_NOTHING}, - {0, 0, 0, SERD_NOTHING}, - {0, 0, 0, SERD_NOTHING}}; +static const WriteContext WRITE_CONTEXT_NULL = {NULL, NULL, NULL}; typedef enum { SEP_NONE, @@ -95,7 +94,7 @@ struct SerdWriterImpl { SerdSyntax syntax; SerdWriterFlags flags; SerdEnv* env; - SerdNode root_node; + SerdNode* root_node; SerdURIView root_uri; SerdURIView base_uri; SerdStack anon_stack; @@ -103,7 +102,7 @@ struct SerdWriterImpl { SerdErrorFunc error_func; void* error_handle; WriteContext context; - SerdNode list_subj; + SerdNode* list_subj; unsigned list_depth; unsigned indent; char* bprefix; @@ -150,7 +149,8 @@ w_err(SerdWriter* writer, SerdStatus st, const char* fmt, ...) va_end(args); } -SERD_PURE_FUNC static WriteContext* +SERD_PURE_FUNC +static WriteContext* anon_stack_top(SerdWriter* writer) { assert(!serd_stack_is_empty(&writer->anon_stack)); @@ -158,18 +158,19 @@ anon_stack_top(SerdWriter* writer) sizeof(WriteContext)); } -static void -copy_node(SerdNode* dst, const SerdNode* src) +static inline SerdNode* +ctx(SerdWriter* writer, const Field field) { - if (src) { - dst->buf = (char*)realloc((char*)dst->buf, src->n_bytes + 1); - dst->n_bytes = src->n_bytes; - dst->flags = src->flags; - dst->type = src->type; - memcpy((char*)dst->buf, src->buf, src->n_bytes + 1); - } else { - dst->type = SERD_NOTHING; + SerdNode* node = NULL; + if (field == FIELD_SUBJECT) { + node = writer->context.subject; + } else if (field == FIELD_PREDICATE) { + node = writer->context.predicate; + } else if (field == FIELD_GRAPH) { + node = writer->context.graph; } + + return node && node->type ? node : NULL; } static size_t @@ -264,6 +265,12 @@ write_uri(SerdWriter* writer, const char* utf8, size_t n_bytes) return len; } +static size_t +write_uri_from_node(SerdWriter* writer, const SerdNode* node) +{ + return write_uri(writer, serd_node_string(node), node->length); +} + static bool lname_must_escape(const char c) { @@ -473,23 +480,26 @@ write_sep(SerdWriter* writer, const Sep sep) static SerdStatus reset_context(SerdWriter* writer, bool graph) { - if (graph) { - writer->context.graph.type = SERD_NOTHING; + if (graph && writer->context.graph) { + memset(writer->context.graph, 0, sizeof(SerdNode)); } - - writer->context.subject.type = SERD_NOTHING; - writer->context.predicate.type = SERD_NOTHING; - writer->empty = false; + if (writer->context.subject) { + memset(writer->context.subject, 0, sizeof(SerdNode)); + } + if (writer->context.predicate) { + memset(writer->context.predicate, 0, sizeof(SerdNode)); + } + writer->empty = false; return SERD_SUCCESS; } static SerdStatus free_context(SerdWriter* writer) { - serd_node_free(&writer->context.graph); - serd_node_free(&writer->context.subject); - serd_node_free(&writer->context.predicate); - return reset_context(writer, true); + serd_node_free(writer->context.graph); + serd_node_free(writer->context.subject); + serd_node_free(writer->context.predicate); + return SERD_SUCCESS; } static bool @@ -507,23 +517,24 @@ write_literal(SerdWriter* writer, const SerdNode* lang, SerdStatementFlags flags) { - if (supports_abbrev(writer) && datatype && datatype->buf) { - const char* type_uri = datatype->buf; + const char* node_str = serd_node_string(node); + const char* type_uri = datatype ? serd_node_string(datatype) : NULL; + if (supports_abbrev(writer) && type_uri) { if (!strncmp(type_uri, NS_XSD, sizeof(NS_XSD) - 1) && (!strcmp(type_uri + sizeof(NS_XSD) - 1, "boolean") || !strcmp(type_uri + sizeof(NS_XSD) - 1, "integer"))) { - sink(node->buf, node->n_bytes, writer); + sink(node_str, node->length, writer); return true; } if (!strncmp(type_uri, NS_XSD, sizeof(NS_XSD) - 1) && !strcmp(type_uri + sizeof(NS_XSD) - 1, "decimal") && - strchr(node->buf, '.') && node->buf[node->n_bytes - 1] != '.') { + strchr(node_str, '.') && node_str[node->length - 1] != '.') { /* xsd:decimal literals without trailing digits, e.g. "5.", can not be written bare in Turtle. We could add a 0 which is prettier, but changes the text and breaks round tripping. */ - sink(node->buf, node->n_bytes, writer); + sink(node_str, node->length, writer); return true; } } @@ -531,17 +542,17 @@ write_literal(SerdWriter* writer, if (supports_abbrev(writer) && (node->flags & (SERD_HAS_NEWLINE | SERD_HAS_QUOTE))) { sink("\"\"\"", 3, writer); - write_text(writer, WRITE_LONG_STRING, node->buf, node->n_bytes); + write_text(writer, WRITE_LONG_STRING, node_str, node->length); sink("\"\"\"", 3, writer); } else { sink("\"", 1, writer); - write_text(writer, WRITE_STRING, node->buf, node->n_bytes); + write_text(writer, WRITE_STRING, node_str, node->length); sink("\"", 1, writer); } - if (lang && lang->buf) { + if (lang && serd_node_string(lang)) { sink("@", 1, writer); - sink(lang->buf, lang->n_bytes, writer); - } else if (datatype && datatype->buf) { + sink(serd_node_string(lang), lang->length, writer); + } else if (type_uri) { sink("^^", 2, writer); return write_node(writer, datatype, NULL, NULL, FIELD_NONE, flags); } @@ -567,24 +578,25 @@ write_uri_node(SerdWriter* const writer, const SerdNode* node, const Field field) { - SerdNode prefix; - SerdStringView suffix; + const SerdNode* prefix = NULL; + SerdStringView suffix = {NULL, 0}; - const bool has_scheme = serd_uri_string_has_scheme(node->buf); + const char* node_str = serd_node_string(node); + const bool has_scheme = serd_uri_string_has_scheme(node_str); if (supports_abbrev(writer)) { - if (field == FIELD_PREDICATE && !strcmp(node->buf, NS_RDF "type")) { + if (field == FIELD_PREDICATE && !strcmp(node_str, NS_RDF "type")) { return sink("a", 1, writer) == 1; } - if (!strcmp(node->buf, NS_RDF "nil")) { + if (!strcmp(node_str, NS_RDF "nil")) { return sink("()", 2, writer) == 2; } if (has_scheme && (writer->flags & SERD_WRITE_CURIED) && serd_env_qualify(writer->env, node, &prefix, &suffix) && - is_name(prefix.buf, prefix.n_bytes) && + is_name(serd_node_string(prefix), serd_node_length(prefix)) && is_name(suffix.buf, suffix.len)) { - write_uri(writer, prefix.buf, prefix.n_bytes); + write_uri_from_node(writer, prefix); sink(":", 1, writer); write_uri(writer, suffix.buf, suffix.len); return true; @@ -592,11 +604,11 @@ write_uri_node(SerdWriter* const writer, } if (!has_scheme && !supports_uriref(writer) && - !serd_env_base_uri(writer->env, NULL)->buf) { + !serd_env_base_uri(writer->env, NULL)) { w_err(writer, SERD_ERR_BAD_ARG, "syntax does not support URI reference <%s>\n", - node->buf); + node_str); return false; } @@ -606,7 +618,7 @@ write_uri_node(SerdWriter* const writer, SerdURIView uri; SerdURIView abs_uri; serd_env_base_uri(writer->env, &in_base_uri); - serd_uri_parse(node->buf, &uri); + serd_uri_parse(node_str, &uri); serd_uri_resolve(&uri, &in_base_uri, &abs_uri); bool rooted = uri_is_under(&writer->base_uri, &writer->root_uri); SerdURIView* root = rooted ? &writer->root_uri : &writer->base_uri; @@ -618,7 +630,7 @@ write_uri_node(SerdWriter* const writer, &uri, &writer->base_uri, root, uri_sink, writer); } } else { - write_uri(writer, node->buf, node->n_bytes); + write_uri_from_node(writer, node); } write_sep(writer, SEP_URI_END); return true; @@ -627,6 +639,8 @@ write_uri_node(SerdWriter* const writer, static bool write_curie(SerdWriter* const writer, const SerdNode* const node) { + const char* node_str = serd_node_string(node); + SerdStringView prefix = {NULL, 0}; SerdStringView suffix = {NULL, 0}; SerdStatus st = SERD_SUCCESS; @@ -634,7 +648,7 @@ write_curie(SerdWriter* const writer, const SerdNode* const node) case SERD_NTRIPLES: case SERD_NQUADS: if ((st = serd_env_expand(writer->env, node, &prefix, &suffix))) { - w_err(writer, st, "undefined namespace prefix `%s'\n", node->buf); + w_err(writer, st, "undefined namespace prefix `%s'\n", node_str); return false; } write_sep(writer, SEP_URI_BEGIN); @@ -644,7 +658,8 @@ write_curie(SerdWriter* const writer, const SerdNode* const node) break; case SERD_TURTLE: case SERD_TRIG: - write_lname(writer, node->buf, node->n_bytes); + write_lname(writer, node_str, node->length); + break; } return true; @@ -656,6 +671,7 @@ write_blank(SerdWriter* const writer, const Field field, const SerdStatementFlags flags) { + const char* node_str = serd_node_string(node); if (supports_abbrev(writer)) { if (is_inline_start(writer, field, flags)) { ++writer->indent; @@ -664,7 +680,7 @@ write_blank(SerdWriter* const writer, if (field == FIELD_SUBJECT && (flags & SERD_LIST_S_BEGIN)) { assert(writer->list_depth == 0); - copy_node(&writer->list_subj, node); + serd_node_set(&writer->list_subj, node); ++writer->list_depth; ++writer->indent; return write_sep(writer, SEP_LIST_BEGIN); @@ -684,12 +700,12 @@ write_blank(SerdWriter* const writer, sink("_:", 2, writer); if (writer->bprefix && - !strncmp(node->buf, writer->bprefix, writer->bprefix_len)) { - sink(node->buf + writer->bprefix_len, - node->n_bytes - writer->bprefix_len, + !strncmp(node_str, writer->bprefix, writer->bprefix_len)) { + sink(node_str + writer->bprefix_len, + node->length - writer->bprefix_len, writer); } else { - sink(node->buf, node->n_bytes, writer); + sink(node_str, node->length, writer); } return true; @@ -705,8 +721,6 @@ write_node(SerdWriter* writer, { bool ret = false; switch (node->type) { - case SERD_NOTHING: - break; case SERD_LITERAL: ret = write_literal(writer, node, datatype, lang, flags); break; @@ -720,7 +734,6 @@ write_node(SerdWriter* writer, ret = write_blank(writer, node, field, flags); break; } - writer->last_sep = SEP_NONE; return ret; } @@ -728,7 +741,7 @@ write_node(SerdWriter* writer, static bool is_resource(const SerdNode* node) { - return node && node->buf && node->type > SERD_LITERAL; + return node && node->type > SERD_LITERAL; } static void @@ -736,7 +749,7 @@ write_pred(SerdWriter* writer, SerdStatementFlags flags, const SerdNode* pred) { write_node(writer, pred, NULL, NULL, FIELD_PREDICATE, flags); write_sep(writer, SEP_P_O); - copy_node(&writer->context.predicate, pred); + serd_node_set(&writer->context.predicate, pred); } static bool @@ -747,13 +760,13 @@ write_list_obj(SerdWriter* writer, const SerdNode* datatype, const SerdNode* lang) { - if (!strcmp(object->buf, NS_RDF "nil")) { + if (!strcmp(serd_node_string(object), NS_RDF "nil")) { --writer->indent; write_sep(writer, SEP_LIST_END); return true; } - if (!strcmp(predicate->buf, NS_RDF "first")) { + if (!strcmp(serd_node_string(predicate), NS_RDF "first")) { write_sep(writer, SEP_LIST_SEP); write_node(writer, object, datatype, lang, FIELD_OBJECT, flags); } @@ -771,8 +784,7 @@ serd_writer_write_statement(SerdWriter* writer, const SerdNode* datatype, const SerdNode* lang) { - if (!is_resource(subject) || !is_resource(predicate) || !object || - !object->buf) { + if (!is_resource(subject) || !is_resource(predicate) || !object) { return SERD_ERR_BAD_ARG; } @@ -797,15 +809,13 @@ serd_writer_write_statement(SerdWriter* writer, return SERD_SUCCESS; } - if ((graph && !serd_node_equals(graph, &writer->context.graph)) || - (!graph && writer->context.graph.type)) { + if ((graph && !serd_node_equals(graph, writer->context.graph)) || + (!graph && ctx(writer, FIELD_GRAPH))) { writer->indent = 0; - - if (writer->context.subject.type) { + if (ctx(writer, FIELD_SUBJECT)) { write_sep(writer, SEP_END_S); } - - if (writer->context.graph.type) { + if (ctx(writer, FIELD_GRAPH)) { write_sep(writer, SEP_GRAPH_END); } @@ -814,23 +824,23 @@ serd_writer_write_statement(SerdWriter* writer, TRY(write_node(writer, graph, datatype, lang, FIELD_GRAPH, flags)); ++writer->indent; write_sep(writer, SEP_GRAPH_BEGIN); - copy_node(&writer->context.graph, graph); + serd_node_set(&writer->context.graph, graph); } } if ((flags & SERD_LIST_CONT)) { if (write_list_obj(writer, flags, predicate, object, datatype, lang)) { // Reached end of list - if (--writer->list_depth == 0 && writer->list_subj.type) { + if (--writer->list_depth == 0 && writer->list_subj) { reset_context(writer, false); - serd_node_free(&writer->context.subject); + serd_node_free(writer->context.subject); writer->context.subject = writer->list_subj; - writer->list_subj = SERD_NODE_NULL; + writer->list_subj = NULL; } return SERD_SUCCESS; } - } else if (serd_node_equals(subject, &writer->context.subject)) { - if (serd_node_equals(predicate, &writer->context.predicate)) { + } else if (serd_node_equals(subject, writer->context.subject)) { + if (serd_node_equals(predicate, writer->context.predicate)) { // Abbreviate S P if (!(flags & SERD_ANON_O_BEGIN)) { ++writer->indent; @@ -842,14 +852,14 @@ serd_writer_write_statement(SerdWriter* writer, } } else { // Abbreviate S - Sep sep = writer->context.predicate.type ? SEP_END_P : SEP_S_P; + Sep sep = ctx(writer, FIELD_PREDICATE) ? SEP_END_P : SEP_S_P; write_sep(writer, sep); write_pred(writer, flags, predicate); write_node(writer, object, datatype, lang, FIELD_OBJECT, flags); } } else { // No abbreviation - if (writer->context.subject.type) { + if (ctx(writer, FIELD_SUBJECT)) { assert(writer->indent > 0); --writer->indent; if (serd_stack_is_empty(&writer->anon_stack)) { @@ -868,7 +878,7 @@ serd_writer_write_statement(SerdWriter* writer, } reset_context(writer, false); - copy_node(&writer->context.subject, subject); + serd_node_set(&writer->context.subject, subject); if (!(flags & SERD_LIST_S_BEGIN)) { write_pred(writer, flags, predicate); @@ -882,15 +892,15 @@ serd_writer_write_statement(SerdWriter* writer, (WriteContext*)serd_stack_push(&writer->anon_stack, sizeof(WriteContext)); *ctx = writer->context; WriteContext new_context = { - serd_node_copy(graph), serd_node_copy(subject), SERD_NODE_NULL}; + serd_node_copy(graph), serd_node_copy(subject), NULL}; if ((flags & SERD_ANON_S_BEGIN)) { new_context.predicate = serd_node_copy(predicate); } writer->context = new_context; } else { - copy_node(&writer->context.graph, graph); - copy_node(&writer->context.subject, subject); - copy_node(&writer->context.predicate, predicate); + serd_node_set(&writer->context.graph, graph); + serd_node_set(&writer->context.subject, subject); + serd_node_set(&writer->context.predicate, predicate); } return SERD_SUCCESS; @@ -902,40 +912,37 @@ serd_writer_end_anon(SerdWriter* writer, const SerdNode* node) if (writer->syntax == SERD_NTRIPLES || writer->syntax == SERD_NQUADS) { return SERD_SUCCESS; } - if (serd_stack_is_empty(&writer->anon_stack) || writer->indent == 0) { w_err(writer, SERD_ERR_UNKNOWN, "unexpected end of anonymous node\n"); return SERD_ERR_UNKNOWN; } - --writer->indent; write_sep(writer, SEP_ANON_END); free_context(writer); writer->context = *anon_stack_top(writer); serd_stack_pop(&writer->anon_stack, sizeof(WriteContext)); - const bool is_subject = serd_node_equals(node, &writer->context.subject); + const bool is_subject = serd_node_equals(node, writer->context.subject); if (is_subject) { - copy_node(&writer->context.subject, node); - writer->context.predicate.type = SERD_NOTHING; + serd_node_set(&writer->context.subject, node); + memset(writer->context.predicate, 0, sizeof(SerdNode)); } - return SERD_SUCCESS; } SerdStatus serd_writer_finish(SerdWriter* writer) { - if (writer->context.subject.type) { + if (ctx(writer, FIELD_SUBJECT)) { write_sep(writer, SEP_END_S); } - - if (writer->context.graph.type) { + if (ctx(writer, FIELD_GRAPH)) { write_sep(writer, SEP_GRAPH_END); } - serd_byte_sink_flush(&writer->byte_sink); - writer->indent = 0; - return free_context(writer); + free_context(writer); + writer->indent = 0; + writer->context = WRITE_CONTEXT_NULL; + return SERD_SUCCESS; } SerdWriter* @@ -952,12 +959,12 @@ serd_writer_new(SerdSyntax syntax, writer->syntax = syntax; writer->flags = flags; writer->env = env; - writer->root_node = SERD_NODE_NULL; + writer->root_node = NULL; writer->root_uri = SERD_URI_NULL; writer->base_uri = base_uri ? *base_uri : SERD_URI_NULL; writer->anon_stack = serd_stack_new(4 * sizeof(WriteContext)); writer->context = context; - writer->list_subj = SERD_NODE_NULL; + writer->list_subj = NULL; writer->empty = true; writer->byte_sink = serd_byte_sink_new( ssink, stream, (flags & SERD_WRITE_BULK) ? SERD_PAGE_SIZE : 1); @@ -996,12 +1003,12 @@ serd_writer_set_base_uri(SerdWriter* writer, const SerdNode* uri) serd_env_base_uri(writer->env, &writer->base_uri); if (writer->syntax == SERD_TURTLE || writer->syntax == SERD_TRIG) { - if (writer->context.graph.type || writer->context.subject.type) { + if (ctx(writer, FIELD_GRAPH) || ctx(writer, FIELD_SUBJECT)) { sink(" .\n\n", 4, writer); reset_context(writer, true); } sink("@base <", 7, writer); - sink(uri->buf, uri->n_bytes, writer); + sink(serd_node_string(uri), uri->length, writer); sink("> .\n", 4, writer); } writer->indent = 0; @@ -1013,14 +1020,13 @@ serd_writer_set_base_uri(SerdWriter* writer, const SerdNode* uri) SerdStatus serd_writer_set_root_uri(SerdWriter* writer, const SerdNode* uri) { - serd_node_free(&writer->root_node); + serd_node_free(writer->root_node); + writer->root_node = NULL; + writer->root_uri = SERD_URI_NULL; - if (uri && uri->buf) { + if (uri) { writer->root_node = serd_node_copy(uri); - serd_uri_parse(uri->buf, &writer->root_uri); - } else { - writer->root_node = SERD_NODE_NULL; - writer->root_uri = SERD_URI_NULL; + serd_uri_parse(serd_node_string(writer->root_node), &writer->root_uri); } return SERD_SUCCESS; @@ -1033,20 +1039,19 @@ serd_writer_set_prefix(SerdWriter* writer, { if (!serd_env_set_prefix(writer->env, name, uri)) { if (writer->syntax == SERD_TURTLE || writer->syntax == SERD_TRIG) { - if (writer->context.graph.type || writer->context.subject.type) { + if (ctx(writer, FIELD_GRAPH) || ctx(writer, FIELD_SUBJECT)) { sink(" .\n\n", 4, writer); reset_context(writer, true); } sink("@prefix ", 8, writer); - sink(name->buf, name->n_bytes, writer); + sink(serd_node_string(name), name->length, writer); sink(": <", 3, writer); - write_uri(writer, uri->buf, uri->n_bytes); + write_uri_from_node(writer, uri); sink("> .\n", 4, writer); } writer->indent = 0; return reset_context(writer, true); } - return SERD_ERR_UNKNOWN; } @@ -1061,7 +1066,7 @@ serd_writer_free(SerdWriter* writer) serd_stack_free(&writer->anon_stack); free(writer->bprefix); serd_byte_sink_free(&writer->byte_sink); - serd_node_free(&writer->root_node); + serd_node_free(writer->root_node); free(writer); } |