aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/n3.c88
-rw-r--r--src/reader.c27
-rw-r--r--src/reader.h4
-rw-r--r--src/stack.h33
-rw-r--r--src/world.c1
5 files changed, 61 insertions, 92 deletions
diff --git a/src/n3.c b/src/n3.c
index a088813a..8de01bd8 100644
--- a/src/n3.c
+++ b/src/n3.c
@@ -307,7 +307,7 @@ read_STRING_LITERAL_LONG(SerdReader* reader, SerdNodeFlags* flags, uint8_t q)
read_UCHAR(reader, ref, &code)) {
r_err(reader, SERD_ERR_BAD_SYNTAX,
"invalid escape `\\%c'\n", peek_byte(reader));
- return pop_node(reader, ref);
+ return NULL;
}
break;
default:
@@ -343,14 +343,14 @@ read_STRING_LITERAL(SerdReader* reader, SerdNodeFlags* flags, uint8_t q)
switch (c) {
case '\n': case '\r':
r_err(reader, SERD_ERR_BAD_SYNTAX, "line end in short string\n");
- return pop_node(reader, ref);
+ return NULL;
case '\\':
eat_byte_safe(reader, c);
if (read_ECHAR(reader, ref, flags) &&
read_UCHAR(reader, ref, &code)) {
r_err(reader, SERD_ERR_BAD_SYNTAX,
"invalid escape `\\%c'\n", peek_byte(reader));
- return pop_node(reader, ref);
+ return NULL;
}
break;
default:
@@ -368,11 +368,7 @@ read_STRING_LITERAL(SerdReader* reader, SerdNodeFlags* flags, uint8_t q)
return NULL;
}
- if (!eat_byte_check(reader, q)) {
- return pop_node(reader, ref);
- }
-
- return ref;
+ return eat_byte_check(reader, q) ? ref : NULL;
}
static SerdNode*
@@ -631,7 +627,7 @@ read_IRIREF(SerdReader* reader)
TRY_RET(eat_byte_check(reader, '<'));
SerdNode* ref = push_node(reader, SERD_URI, "", 0);
if (!ref || (!fancy_syntax(reader) && !read_IRIREF_scheme(reader, ref))) {
- return pop_node(reader, ref);
+ return NULL;
}
uint32_t code = 0;
@@ -641,19 +637,19 @@ read_IRIREF(SerdReader* reader)
case '"': case '<': case '^': case '`': case '{': case '|': case '}':
r_err(reader, SERD_ERR_BAD_SYNTAX,
"invalid IRI character `%c'\n", c);
- return pop_node(reader, ref);
+ return NULL;
case '>':
return ref;
case '\\':
if (read_UCHAR(reader, ref, &code)) {
r_err(reader, SERD_ERR_BAD_SYNTAX, "invalid IRI escape\n");
- return pop_node(reader, ref);
+ return NULL;
}
switch (code) {
case 0: case ' ': case '<': case '>':
r_err(reader, SERD_ERR_BAD_SYNTAX,
"invalid escaped IRI character %X %c\n", code, code);
- return pop_node(reader, ref);
+ return NULL;
}
break;
default:
@@ -666,7 +662,7 @@ read_IRIREF(SerdReader* reader)
"invalid IRI character (escape %%%02X)\n", c, c);
}
if (reader->strict) {
- return pop_node(reader, ref);
+ return NULL;
}
reader->status = SERD_FAILURE;
push_byte(reader, ref, c);
@@ -674,13 +670,13 @@ read_IRIREF(SerdReader* reader)
push_byte(reader, ref, c);
} else if (read_utf8_character(reader, ref, c)) {
if (reader->strict) {
- return pop_node(reader, ref);
+ return NULL;
}
reader->status = SERD_FAILURE;
}
}
}
- return pop_node(reader, ref);
+ return NULL;
}
static bool
@@ -776,8 +772,6 @@ read_number(SerdReader* reader,
*dest = ref;
return true;
except:
- pop_node(reader, *datatype);
- pop_node(reader, ref);
return r_err(reader, SERD_ERR_BAD_SYNTAX, "bad number syntax\n");
}
@@ -825,9 +819,8 @@ read_literal(SerdReader* reader,
*dest = str;
return true;
except:
- *datatype = pop_node(reader, *datatype);
- *lang = pop_node(reader, *lang);
- pop_node(reader, str);
+ *datatype = NULL;
+ *lang = NULL;
return r_err(reader, SERD_ERR_BAD_SYNTAX, "bad literal syntax\n");
}
@@ -846,6 +839,7 @@ is_token_end(uint8_t c)
static bool
read_verb(SerdReader* reader, SerdNode** dest)
{
+ const size_t orig_stack_size = reader->stack.size;
if (peek_byte(reader) == '<') {
return (*dest = read_IRIREF(reader));
}
@@ -863,12 +857,12 @@ read_verb(SerdReader* reader, SerdNode** dest)
if (!st && node->n_bytes == 1 &&
serd_node_get_string(node)[0] == 'a' &&
is_token_end(peek_byte(reader))) {
- pop_node(reader, *dest);
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
return (*dest = push_node(reader, SERD_URI, NS_RDF "type", 47));
} else if (st > SERD_FAILURE ||
!read_PrefixedName(reader, *dest, false, &ate_dot) ||
ate_dot) {
- *dest = pop_node(reader, *dest);
+ *dest = NULL;
return r_err(reader, SERD_ERR_BAD_SYNTAX, "bad verb\n");
}
@@ -892,7 +886,7 @@ read_BLANK_NODE_LABEL(SerdReader* reader, bool* ate_dot)
push_byte(reader, n, eat_byte_safe(reader, c));
} else if (read_PN_CHARS(reader, n)) {
r_err(reader, SERD_ERR_BAD_SYNTAX, "invalid name start character\n");
- return pop_node(reader, n);
+ return NULL;
}
while ((c = peek_byte(reader))) { // Middle: (PN_CHARS | '.')*
@@ -919,7 +913,7 @@ read_BLANK_NODE_LABEL(SerdReader* reader, bool* ate_dot)
} else if (reader->seen_genid && buf[reader->bprefix_len] == 'B') {
r_err(reader, SERD_ERR_ID_CLASH,
"found both `b' and `B' blank IDs, prefix required\n");
- return pop_node(reader, n);
+ return NULL;
}
}
}
@@ -996,9 +990,7 @@ read_object(SerdReader* reader, ReadContext* ctx, bool emit, bool* ate_dot)
static const char* const XSD_BOOLEAN = NS_XSD "boolean";
static const size_t XSD_BOOLEAN_LEN = 40;
-#ifndef NDEBUG
const size_t orig_stack_size = reader->stack.size;
-#endif
bool ret = false;
bool simple = (ctx->subject != 0);
@@ -1077,9 +1069,7 @@ read_object(SerdReader* reader, ReadContext* ctx, bool emit, bool* ate_dot)
}
except:
- pop_node(reader, lang);
- pop_node(reader, datatype);
- pop_node(reader, o);
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
#ifndef NDEBUG
assert(reader->stack.size == orig_stack_size);
#endif
@@ -1104,11 +1094,13 @@ read_objectList(SerdReader* reader, ReadContext ctx, bool* ate_dot)
static bool
read_predicateObjectList(SerdReader* reader, ReadContext ctx, bool* ate_dot)
{
+ const size_t orig_stack_size = reader->stack.size;
+
while (read_verb(reader, &ctx.predicate) &&
read_ws_star(reader) &&
read_objectList(reader, ctx, ate_dot)) {
- ctx.predicate = pop_node(reader, ctx.predicate);
if (*ate_dot) {
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
return true;
}
@@ -1118,9 +1110,11 @@ read_predicateObjectList(SerdReader* reader, ReadContext ctx, bool* ate_dot)
read_ws_star(reader);
switch (c = peek_byte(reader)) {
case 0:
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
return r_err(reader, SERD_ERR_BAD_SYNTAX,
"unexpected end of file\n");
case '.': case ']': case '}':
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
return true;
case ';':
eat_byte_safe(reader, c);
@@ -1129,18 +1123,19 @@ read_predicateObjectList(SerdReader* reader, ReadContext ctx, bool* ate_dot)
} while (c == ';');
if (!ate_semi) {
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
return r_err(reader, SERD_ERR_BAD_SYNTAX, "missing ';' or '.'\n");
}
}
- return pop_node(reader, ctx.predicate);
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
+ ctx.predicate = 0;
+ return false;
}
static bool
end_collection(SerdReader* reader, ReadContext ctx, SerdNode* n1, SerdNode* n2, bool ret)
{
- pop_node(reader, n2);
- pop_node(reader, n1);
*ctx.flags &= ~SERD_LIST_CONT;
return ret && (eat_byte_safe(reader, ')') == ')');
}
@@ -1225,7 +1220,7 @@ read_subject(SerdReader* reader, ReadContext ctx, SerdNode** dest, char* s_type)
default:
TRY_RET(read_iri(reader, dest, &ate_dot));
}
- return ate_dot ? pop_node(reader, *dest) : *dest;
+ return ate_dot ? NULL : *dest;
}
static SerdNode*
@@ -1280,7 +1275,6 @@ read_base(SerdReader* reader, bool sparql, bool token)
} else if (reader->sink->base) {
reader->sink->base(reader->sink->handle, uri);
}
- pop_node(reader, uri);
read_ws_star(reader);
if (!sparql) {
@@ -1305,25 +1299,22 @@ read_prefixID(SerdReader* reader, bool sparql, bool token)
if (!name) {
return false;
} else if (read_PN_PREFIX(reader, name) > SERD_FAILURE) {
- return pop_node(reader, name);
+ return false;
}
if (eat_byte_check(reader, ':') != ':') {
- return pop_node(reader, name);
+ return false;
}
read_ws_star(reader);
const SerdNode* uri = read_IRIREF(reader);
if (!uri) {
- pop_node(reader, name);
return false;
}
if (reader->sink->prefix) {
ret = !reader->sink->prefix(reader->sink->handle, name, uri);
}
- pop_node(reader, uri);
- pop_node(reader, name);
if (!sparql) {
read_ws_star(reader);
return eat_byte_check(reader, '.');
@@ -1362,6 +1353,8 @@ read_wrappedGraph(SerdReader* reader, ReadContext* ctx)
TRY_RET(eat_byte_check(reader, '{'));
read_ws_star(reader);
while (peek_byte(reader) != '}') {
+ const size_t orig_stack_size = reader->stack.size;
+
ctx->subject = 0;
SerdNode* subj = read_subject(reader, *ctx, &ctx->subject, &s_type);
if (!subj && ctx->subject) {
@@ -1372,7 +1365,7 @@ read_wrappedGraph(SerdReader* reader, ReadContext* ctx)
return r_err(reader, SERD_ERR_BAD_SYNTAX,
"missing predicate object list\n");
}
- pop_node(reader, subj);
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
read_ws_star(reader);
if (peek_byte(reader) == '.') {
eat_byte_safe(reader, '.');
@@ -1433,7 +1426,6 @@ read_n3_statement(SerdReader* reader)
TRY_RET((ctx.graph = read_labelOrSubject(reader, ctx)));
read_ws_star(reader);
TRY_RET(read_wrappedGraph(reader, &ctx));
- pop_node(reader, ctx.graph);
ctx.graph = 0;
read_ws_star(reader);
} else if (read_ws_star(reader) && peek_byte(reader) == '{') {
@@ -1444,7 +1436,6 @@ read_n3_statement(SerdReader* reader)
ctx.graph = subj;
ctx.subject = subj = 0;
TRY_RET(read_wrappedGraph(reader, &ctx));
- pop_node(reader, ctx.graph);
read_ws_star(reader);
} else if (!subj) {
ret = r_err(reader, SERD_ERR_BAD_SYNTAX, "bad subject\n");
@@ -1454,7 +1445,6 @@ read_n3_statement(SerdReader* reader)
read_ws_star(reader);
ret = (eat_byte_check(reader, '.') == '.');
}
- pop_node(reader, subj);
break;
}
return ret;
@@ -1472,13 +1462,16 @@ SerdStatus
read_turtleTrigDoc(SerdReader* reader)
{
while (!reader->source.eof) {
+ const size_t orig_stack_size = reader->stack.size;
if (!read_n3_statement(reader)) {
if (reader->strict) {
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
return SERD_ERR_UNKNOWN;
}
skip_until(reader, '\n');
reader->status = SERD_SUCCESS;
}
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
}
return reader->status;
}
@@ -1487,6 +1480,8 @@ SerdStatus
read_nquadsDoc(SerdReader* reader)
{
while (!reader->source.eof) {
+ const size_t orig_stack_size = reader->stack.size;
+
SerdStatementFlags flags = 0;
ReadContext ctx = { 0, 0, 0, 0, 0, 0, &flags };
bool ate_dot = false;
@@ -1533,10 +1528,7 @@ read_nquadsDoc(SerdReader* reader)
break;
}
- pop_node(reader, ctx.graph);
- pop_node(reader, ctx.lang);
- pop_node(reader, ctx.datatype);
- pop_node(reader, ctx.object);
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
}
return reader->status;
}
diff --git a/src/reader.c b/src/reader.c
index 31ee5287..8af73f12 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -71,6 +71,13 @@ SerdNode*
push_node_padded(SerdReader* reader, size_t maxlen,
SerdType type, const char* str, size_t n_bytes)
{
+ // Push a null byte to ensure the previous node was null terminated
+ char* terminator = (char*)serd_stack_push(&reader->stack, 1);
+ if (!terminator) {
+ return NULL;
+ }
+ *terminator = 0;
+
void* mem = serd_stack_push_aligned(
&reader->stack, sizeof(SerdNode) + maxlen + 1, sizeof(SerdNode));
@@ -90,7 +97,7 @@ push_node_padded(SerdReader* reader, size_t maxlen,
#ifdef SERD_STACK_CHECK
reader->allocs = realloc(
reader->allocs, sizeof(reader->allocs) * (++reader->n_allocs));
- reader->allocs[reader->n_allocs - 1] = (mem - reader->stack.buf);
+ reader->allocs[reader->n_allocs - 1] = node;
#endif
return node;
}
@@ -101,21 +108,6 @@ push_node(SerdReader* reader, SerdType type, const char* str, size_t n_bytes)
return push_node_padded(reader, n_bytes, type, str, n_bytes);
}
-SerdNode*
-pop_node(SerdReader* reader, const SerdNode* node)
-{
- if (node && node != reader->rdf_first && node != reader->rdf_rest
- && node != reader->rdf_nil) {
-#ifdef SERD_STACK_CHECK
- SERD_STACK_ASSERT_TOP(reader, node);
- --reader->n_allocs;
-#endif
- char* const top = reader->stack.buf + reader->stack.size;
- serd_stack_pop_aligned(&reader->stack, top - (char*)node);
- }
- return NULL;
-}
-
bool
emit_statement(SerdReader* reader,
ReadContext ctx,
@@ -190,9 +182,6 @@ serd_reader_set_strict(SerdReader* reader, bool strict)
void
serd_reader_free(SerdReader* 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);
#ifdef SERD_STACK_CHECK
diff --git a/src/reader.h b/src/reader.h
index 92baac3f..8c201e60 100644
--- a/src/reader.h
+++ b/src/reader.h
@@ -87,8 +87,6 @@ size_t genid_size(SerdReader* reader);
SerdNode* blank_id(SerdReader* reader);
void set_blank_id(SerdReader* reader, SerdNode* node, size_t buf_size);
-SerdNode* pop_node(SerdReader* reader, const SerdNode* node);
-
bool emit_statement(SerdReader* reader,
ReadContext ctx,
SerdNode* o,
@@ -148,7 +146,7 @@ eat_string(SerdReader* reader, const char* str, unsigned n)
static inline SerdStatus
push_byte(SerdReader* reader, SerdNode* node, const uint8_t c)
{
- SERD_STACK_ASSERT_TOP(reader, ref);
+ SERD_STACK_ASSERT_TOP(reader, node);
char* const s = (char*)serd_stack_push(&reader->stack, 1);
if (!s) {
return SERD_ERR_OVERFLOW;
diff --git a/src/stack.h b/src/stack.h
index 3848af66..466a6027 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -20,6 +20,7 @@
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
+#include <string.h>
/** An offset to start the stack at. Note 0 is reserved for NULL. */
#define SERD_STACK_BOTTOM sizeof(void*)
@@ -75,40 +76,28 @@ serd_stack_pop(SerdStack* stack, size_t n_bytes)
stack->size -= n_bytes;
}
+static inline void
+serd_stack_pop_to(SerdStack* stack, size_t n_bytes)
+{
+ assert(stack->size >= n_bytes);
+ stack->size = n_bytes;
+}
+
static inline void*
serd_stack_push_aligned(SerdStack* stack, size_t n_bytes, size_t align)
{
- // Push one byte to ensure space for a pad count
- if (!serd_stack_push(stack, 1)) {
- return NULL;
- }
-
// Push padding if necessary
const uint8_t pad = align - stack->size % align;
if (pad > 0) {
- if (!serd_stack_push(stack, pad)) {
+ void* padding = serd_stack_push(stack, pad);
+ if (!padding) {
return NULL;
}
+ memset(padding, 0, pad);
}
- // Set top of stack to pad count so we can properly pop later
- stack->buf[stack->size - 1] = pad;
-
// Push requested space at aligned location
return serd_stack_push(stack, n_bytes);
}
-static inline void
-serd_stack_pop_aligned(SerdStack* stack, size_t n_bytes)
-{
- // Pop requested space down to aligned location
- serd_stack_pop(stack, n_bytes);
-
- // Get amount of padding from top of stack
- const uint8_t pad = stack->buf[stack->size - 1];
-
- // Pop padding and pad count
- serd_stack_pop(stack, pad + 1);
-}
-
#endif // SERD_STACK_H
diff --git a/src/world.c b/src/world.c
index fbe9da3f..2d0632b4 100644
--- a/src/world.c
+++ b/src/world.c
@@ -86,6 +86,7 @@ void
serd_world_free(SerdWorld* world)
{
serd_nodes_free(world->nodes);
+ serd_node_free(world->blank_node);
free(world);
}