aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/n3.c111
-rw-r--r--src/reader.c34
-rw-r--r--src/reader.h15
-rw-r--r--src/stack.h34
4 files changed, 55 insertions, 139 deletions
diff --git a/src/n3.c b/src/n3.c
index e35b8940..36f90c4f 100644
--- a/src/n3.c
+++ b/src/n3.c
@@ -740,7 +740,6 @@ read_IRIREF(SerdReader* const reader, SerdNode** const dest)
*dest = push_node(reader, SERD_URI, "", 0);
if (!fancy_syntax(reader) && read_IRIREF_scheme(reader, *dest)) {
- *dest = pop_node(reader, *dest);
return r_err(reader, SERD_BAD_SYNTAX, "expected IRI scheme\n");
}
@@ -751,24 +750,18 @@ read_IRIREF(SerdReader* const reader, SerdNode** const dest)
switch (c) {
case '"':
case '<':
- *dest = pop_node(reader, *dest);
return r_err(reader, SERD_BAD_SYNTAX, "invalid IRI character '%c'\n", c);
-
case '>':
return SERD_SUCCESS;
-
case '\\':
if (read_UCHAR(reader, *dest, &code)) {
- *dest = pop_node(reader, *dest);
return r_err(reader, SERD_BAD_SYNTAX, "invalid IRI escape\n");
}
-
switch (code) {
case 0:
case ' ':
case '<':
case '>':
- *dest = pop_node(reader, *dest);
return r_err(reader,
SERD_BAD_SYNTAX,
"invalid escaped IRI character U+%04X\n",
@@ -777,15 +770,12 @@ read_IRIREF(SerdReader* const reader, SerdNode** const dest)
break;
}
break;
-
case '^':
case '`':
case '{':
case '|':
case '}':
- *dest = pop_node(reader, *dest);
return r_err(reader, SERD_BAD_SYNTAX, "invalid IRI character '%c'\n", c);
-
default:
if (c <= 0x20) {
st = r_err(reader,
@@ -802,14 +792,12 @@ read_IRIREF(SerdReader* const reader, SerdNode** const dest)
push_byte(reader, *dest, c);
} else if (read_utf8_character(reader, *dest, (uint8_t)c)) {
if (reader->strict) {
- *dest = pop_node(reader, *dest);
return SERD_BAD_SYNTAX;
}
}
}
}
- *dest = pop_node(reader, *dest);
return st;
}
@@ -952,7 +940,7 @@ read_literal(SerdReader* const reader,
SerdStatus st = read_String(reader, *dest, flags);
if (st) {
- *dest = pop_node(reader, *dest);
+ *dest = NULL;
return st;
}
@@ -961,10 +949,7 @@ read_literal(SerdReader* const reader,
skip_byte(reader, '@');
*flags |= SERD_HAS_LANGUAGE;
if ((st = read_LANGTAG(reader, lang))) {
- *datatype = pop_node(reader, *datatype);
- *lang = pop_node(reader, *lang);
- *dest = pop_node(reader, *dest);
- return r_err(reader, st, "bad language tag\n");
+ return r_err(reader, st, "bad literal\n");
}
break;
case '^':
@@ -975,9 +960,6 @@ read_literal(SerdReader* const reader,
*flags |= SERD_HAS_DATATYPE;
if ((st = read_iri(reader, datatype, ate_dot))) {
- *datatype = pop_node(reader, *datatype);
- *lang = pop_node(reader, *lang);
- *dest = pop_node(reader, *dest);
return r_err(reader, st, "bad datatype\n");
}
break;
@@ -988,6 +970,7 @@ read_literal(SerdReader* const reader,
static SerdStatus
read_verb(SerdReader* const reader, SerdNode** const dest)
{
+ const size_t orig_stack_size = reader->stack.size;
if (peek_byte(reader) == '<') {
return read_IRIREF(reader, dest);
}
@@ -1005,14 +988,14 @@ read_verb(SerdReader* const reader, SerdNode** const dest)
const int next = peek_byte(reader);
if (!st && node->length == 1 && serd_node_string(node)[0] == 'a' &&
next != ':' && !is_PN_CHARS_BASE((uint32_t)next)) {
- pop_node(reader, *dest);
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
*dest = push_node(reader, SERD_URI, NS_RDF "type", 47);
return SERD_SUCCESS;
}
if (st > SERD_FAILURE ||
(st = read_PrefixedName(reader, *dest, false, &ate_dot)) || ate_dot) {
- *dest = pop_node(reader, *dest);
+ *dest = NULL;
st = st > SERD_FAILURE ? st : SERD_BAD_SYNTAX;
return r_err(reader, st, "bad verb\n");
}
@@ -1041,8 +1024,7 @@ read_BLANK_NODE_LABEL(SerdReader* const reader,
if (is_digit(c) || c == '_') {
push_byte(reader, n, eat_byte_safe(reader, c));
} else if ((st = read_PN_CHARS(reader, n))) {
- st = st > SERD_FAILURE ? st : SERD_BAD_SYNTAX;
- *dest = pop_node(reader, n);
+ st = st > SERD_FAILURE ? st : SERD_BAD_SYNTAX;
return r_err(reader, st, "invalid name start\n");
}
@@ -1072,7 +1054,6 @@ read_BLANK_NODE_LABEL(SerdReader* const reader,
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, n);
return r_err(reader,
SERD_BAD_LABEL,
"found both 'b' and 'B' blank IDs, prefix required\n");
@@ -1145,9 +1126,7 @@ read_object(SerdReader* const reader,
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
SerdStatus st = SERD_FAILURE;
@@ -1227,7 +1206,6 @@ read_object(SerdReader* const reader,
} else {
if ((st = read_PrefixedName(reader, o, false, ate_dot))) {
st = st > SERD_FAILURE ? st : SERD_BAD_SYNTAX;
- pop_node(reader, o);
return r_err(reader, st, "expected prefixed name\n");
}
}
@@ -1246,9 +1224,7 @@ read_object(SerdReader* const reader,
return SERD_SUCCESS;
}
- 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
@@ -1277,11 +1253,13 @@ read_predicateObjectList(SerdReader* const reader,
ReadContext ctx,
bool* const ate_dot)
{
+ const size_t orig_stack_size = reader->stack.size;
+
SerdStatus st = SERD_SUCCESS;
while (!(st = read_verb(reader, &ctx.predicate)) && read_ws_star(reader) &&
!(st = 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 SERD_SUCCESS;
}
@@ -1291,10 +1269,12 @@ read_predicateObjectList(SerdReader* const reader,
read_ws_star(reader);
switch (c = peek_byte(reader)) {
case EOF:
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
return r_err(reader, SERD_BAD_SYNTAX, "unexpected end of file\n");
case '.':
case ']':
case '}':
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
return SERD_SUCCESS;
case ';':
skip_byte(reader, c);
@@ -1303,29 +1283,24 @@ read_predicateObjectList(SerdReader* const reader,
} while (c == ';');
if (!ate_semi) {
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
return r_err(reader, SERD_BAD_SYNTAX, "missing ';' or '.'\n");
}
}
- ctx.predicate = pop_node(reader, ctx.predicate);
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
+ ctx.predicate = 0;
return st;
}
static SerdStatus
-end_collection(SerdReader* const reader,
- const ReadContext ctx,
- SerdNode* const n1,
- SerdNode* const n2,
- const SerdStatus st)
+end_collection(SerdReader* const reader, ReadContext ctx, const SerdStatus st)
{
- pop_node(reader, n2);
- pop_node(reader, n1);
*ctx.flags &= ~(unsigned)SERD_LIST_CONT;
if (!st) {
return (eat_byte_check(reader, ')') == ')') ? SERD_SUCCESS
: SERD_BAD_SYNTAX;
}
-
return st;
}
@@ -1351,14 +1326,13 @@ read_collection(SerdReader* const reader,
}
if (end) {
- return end_collection(reader, ctx, 0, 0, st);
+ return end_collection(reader, ctx, st);
}
/* The order of node allocation here is necessarily not in stack order,
so we create two nodes and recycle them throughout. */
SerdNode* n1 =
push_node_padded(reader, genid_size(reader), SERD_BLANK, "", 0);
- SerdNode* n2 = 0;
SerdNode* node = n1;
SerdNode* rest = 0;
@@ -1372,14 +1346,14 @@ read_collection(SerdReader* const reader,
ctx.predicate = reader->rdf_first;
bool ate_dot = false;
if ((st = read_object(reader, &ctx, true, &ate_dot)) || ate_dot) {
- return end_collection(reader, ctx, n1, n2, st);
+ return end_collection(reader, ctx, st);
}
if (!(end = peek_delim(reader, ')'))) {
/* Give rest a new ID. Done as late as possible to ensure it is
used and > IDs generated by read_object above. */
if (!rest) {
- rest = n2 = blank_id(reader); // First pass, push
+ rest = blank_id(reader); // First pass, push
} else {
set_blank_id(reader, rest, genid_size(reader));
}
@@ -1395,7 +1369,7 @@ read_collection(SerdReader* const reader,
node = ctx.subject; // invariant
}
- return end_collection(reader, ctx, n1, n2, st);
+ return end_collection(reader, ctx, st);
}
static SerdStatus
@@ -1421,7 +1395,6 @@ read_subject(SerdReader* const reader,
}
if (ate_dot) {
- pop_node(reader, *dest);
return r_err(reader, SERD_BAD_SYNTAX, "subject ends with '.'\n");
}
@@ -1485,7 +1458,6 @@ read_base(SerdReader* const reader, const bool sparql, const bool token)
SerdNode* uri = NULL;
TRY(st, read_IRIREF(reader, &uri));
TRY(st, serd_sink_write_base(reader->sink, uri));
- pop_node(reader, uri);
read_ws_star(reader);
if (!sparql) {
@@ -1516,7 +1488,6 @@ read_prefixID(SerdReader* const reader, const bool sparql, const bool token)
TRY_FAILING(st, read_PN_PREFIX(reader, name));
if (eat_byte_check(reader, ':') != ':') {
- pop_node(reader, name);
return SERD_BAD_SYNTAX;
}
@@ -1526,8 +1497,6 @@ read_prefixID(SerdReader* const reader, const bool sparql, const bool token)
st = serd_sink_write_prefix(reader->sink, name, uri);
- pop_node(reader, uri);
- pop_node(reader, name);
if (!sparql) {
read_ws_star(reader);
st = eat_byte_check(reader, '.') ? SERD_SUCCESS : SERD_BAD_SYNTAX;
@@ -1571,8 +1540,10 @@ read_wrappedGraph(SerdReader* const reader, ReadContext* const ctx)
read_ws_star(reader);
while (peek_byte(reader) != '}') {
- bool ate_dot = false;
- int s_type = 0;
+ const size_t orig_stack_size = reader->stack.size;
+ bool ate_dot = false;
+ int s_type = 0;
+
ctx->subject = 0;
SerdStatus st = read_subject(reader, *ctx, &ctx->subject, &s_type);
if (st) {
@@ -1583,7 +1554,7 @@ read_wrappedGraph(SerdReader* const reader, ReadContext* const ctx)
return r_err(reader, st, "bad predicate object list\n");
}
- ctx->subject = pop_node(reader, ctx->subject);
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
read_ws_star(reader);
if (peek_byte(reader) == '.') {
skip_byte(reader, '.');
@@ -1611,10 +1582,6 @@ tokcmp(SerdNode* const node, const char* const tok, const size_t n)
SerdStatus
read_n3_statement(SerdReader* const reader)
{
-#ifndef NDEBUG
- const size_t orig_stack_size = reader->stack.size;
-#endif
-
SerdStatementFlags flags = 0;
ReadContext ctx = {0, 0, 0, 0, 0, 0, &flags};
bool ate_dot = false;
@@ -1651,12 +1618,11 @@ read_n3_statement(SerdReader* const reader)
} else if (!tokcmp(ctx.subject, "prefix", 6)) {
st = read_prefixID(reader, true, false);
} else if (!tokcmp(ctx.subject, "graph", 5)) {
- ctx.subject = pop_node(reader, ctx.subject);
+ ctx.subject = NULL;
read_ws_star(reader);
TRY(st, read_labelOrSubject(reader, &ctx.graph));
read_ws_star(reader);
TRY(st, read_wrappedGraph(reader, &ctx));
- pop_node(reader, ctx.graph);
ctx.graph = 0;
read_ws_star(reader);
} else if (!tokcmp(ctx.subject, "true", 4) ||
@@ -1667,9 +1633,8 @@ read_n3_statement(SerdReader* const reader)
return r_err(reader, SERD_BAD_SYNTAX, "invalid graph name\n");
}
ctx.graph = ctx.subject;
- ctx.subject = 0;
+ ctx.subject = NULL;
TRY(st, read_wrappedGraph(reader, &ctx));
- pop_node(reader, ctx.graph);
read_ws_star(reader);
} else if ((st = read_triples(reader, ctx, &ate_dot))) {
if (st == SERD_FAILURE && s_type == '[') {
@@ -1686,15 +1651,9 @@ read_n3_statement(SerdReader* const reader)
st =
(eat_byte_check(reader, '.') == '.') ? SERD_SUCCESS : SERD_BAD_SYNTAX;
}
-
- ctx.subject = pop_node(reader, ctx.subject);
break;
}
-#ifndef NDEBUG
- assert(reader->stack.size == orig_stack_size);
-#endif
-
return st;
}
@@ -1715,13 +1674,18 @@ SerdStatus
read_turtleTrigDoc(SerdReader* const reader)
{
while (!reader->source.eof) {
- const SerdStatus st = read_n3_statement(reader);
+ const size_t orig_stack_size = reader->stack.size;
+ const SerdStatus st = read_n3_statement(reader);
+
if (st > SERD_FAILURE) {
if (reader->strict) {
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
return st;
}
serd_reader_skip_until_byte(reader, '\n');
}
+
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
}
return SERD_SUCCESS;
@@ -1775,11 +1739,6 @@ read_nquads_statement(SerdReader* const reader)
TRY(st, emit_statement(reader, ctx, ctx.object));
- pop_node(reader, ctx.graph);
- pop_node(reader, ctx.lang);
- pop_node(reader, ctx.datatype);
- pop_node(reader, ctx.object);
-
return SERD_SUCCESS;
}
@@ -1789,7 +1748,11 @@ read_nquadsDoc(SerdReader* const reader)
SerdStatus st = SERD_SUCCESS;
while (!reader->source.eof && !st) {
+ const size_t orig_stack_size = reader->stack.size;
+
st = read_nquads_statement(reader);
+
+ serd_stack_pop_to(&reader->stack, orig_stack_size);
}
return st;
diff --git a/src/reader.c b/src/reader.c
index 3b4dfd2b..ae50adab 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -69,6 +69,13 @@ push_node_padded(SerdReader* const reader,
const char* const str,
const size_t length)
{
+ // 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));
@@ -85,12 +92,6 @@ push_node_padded(SerdReader* const reader,
char* buf = (char*)(node + 1);
memcpy(buf, str, length + 1);
-#ifdef SERD_STACK_CHECK
- reader->allocs = (SerdNode**)realloc(
- reader->allocs, sizeof(reader->allocs) * (++reader->n_allocs));
- reader->allocs[reader->n_allocs - 1] =
- (SerdNode*)((char*)mem - reader->stack.buf);
-#endif
return node;
}
@@ -103,21 +104,6 @@ push_node(SerdReader* const reader,
return push_node_padded(reader, length, type, str, length);
}
-SerdNode*
-pop_node(SerdReader* const reader, const SerdNode* const 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, (size_t)(top - (char*)node));
- }
- return NULL;
-}
-
SerdStatus
emit_statement(SerdReader* const reader,
const ReadContext ctx,
@@ -204,15 +190,9 @@ serd_reader_free(SerdReader* const reader)
return;
}
- pop_node(reader, reader->rdf_nil);
- pop_node(reader, reader->rdf_rest);
- pop_node(reader, reader->rdf_first);
serd_reader_finish(reader);
serd_node_free(reader->default_graph);
-#ifdef SERD_STACK_CHECK
- free(reader->allocs);
-#endif
free(reader->stack.buf);
free(reader->bprefix);
free(reader);
diff --git a/src/reader.h b/src/reader.h
index a39fc278..d126aeaa 100644
--- a/src/reader.h
+++ b/src/reader.h
@@ -22,13 +22,6 @@
#include <stdint.h>
#include <stdio.h>
-#ifdef SERD_STACK_CHECK
-# define SERD_STACK_ASSERT_TOP(reader, ref) \
- assert(ref == reader->allocs[reader->n_allocs - 1]);
-#else
-# define SERD_STACK_ASSERT_TOP(reader, ref)
-#endif
-
typedef struct {
SerdNode* graph;
SerdNode* subject;
@@ -56,10 +49,6 @@ struct SerdReaderImpl {
size_t bprefix_len;
bool strict; ///< True iff strict parsing
bool seen_genid;
-#ifdef SERD_STACK_CHECK
- SerdNode** allocs; ///< Stack of push offsets
- size_t n_allocs; ///< Number of stack pushes
-#endif
};
SERD_LOG_FUNC(3, 4)
@@ -88,9 +77,6 @@ blank_id(SerdReader* reader);
void
set_blank_id(SerdReader* reader, SerdNode* node, size_t buf_size);
-SerdNode*
-pop_node(SerdReader* reader, const SerdNode* node);
-
SerdStatus
emit_statement(SerdReader* reader, ReadContext ctx, SerdNode* o);
@@ -161,7 +147,6 @@ static inline SerdStatus
push_byte(SerdReader* reader, SerdNode* node, const int c)
{
assert(c != EOF);
- SERD_STACK_ASSERT_TOP(reader, ref);
char* const s = (char*)serd_stack_push(&reader->stack, 1);
if (!s) {
diff --git a/src/stack.h b/src/stack.h
index e6e46372..4592705e 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -7,8 +7,8 @@
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
-#include <stdint.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*)
@@ -68,40 +68,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 size_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] = (char)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 = (uint8_t)stack->buf[stack->size - 1];
-
- // Pop padding and pad count
- serd_stack_pop(stack, pad + 1U);
-}
-
#endif // SERD_SRC_STACK_H