aboutsummaryrefslogtreecommitdiffstats
path: root/src/reader.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2021-07-08 16:15:46 -0400
committerDavid Robillard <d@drobilla.net>2023-12-02 16:27:02 -0500
commitfb95ceca3b744e47e973585aa682515365ac9eb0 (patch)
tree264e30801d634ea580478a10095938448b4962c8 /src/reader.c
parent8978501e5cf06f366eb14f6ef5f5f7f2f8e34986 (diff)
downloadserd-fb95ceca3b744e47e973585aa682515365ac9eb0.tar.gz
serd-fb95ceca3b744e47e973585aa682515365ac9eb0.tar.bz2
serd-fb95ceca3b744e47e973585aa682515365ac9eb0.zip
Use a fixed-size reader stack
Diffstat (limited to 'src/reader.c')
-rw-r--r--src/reader.c84
1 files changed, 49 insertions, 35 deletions
diff --git a/src/reader.c b/src/reader.c
index 944c8d09..3b4dfd2b 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -34,9 +34,10 @@ r_err(SerdReader* const reader, const SerdStatus st, const char* const fmt, ...)
}
void
-set_blank_id(SerdReader* const reader, const Ref ref, const size_t buf_size)
+set_blank_id(SerdReader* const reader,
+ SerdNode* const node,
+ const size_t buf_size)
{
- SerdNode* node = deref(reader, ref);
char* buf = (char*)(node + 1);
const char* prefix = reader->bprefix ? (const char*)reader->bprefix : "";
@@ -50,15 +51,18 @@ genid_size(const SerdReader* const reader)
return reader->bprefix_len + 1 + 10 + 1; // + "b" + UINT32_MAX + \0
}
-Ref
+SerdNode*
blank_id(SerdReader* const reader)
{
- Ref ref = push_node_padded(reader, genid_size(reader), SERD_BLANK, "", 0);
- set_blank_id(reader, ref, genid_size(reader));
+ SerdNode* ref =
+ push_node_padded(reader, genid_size(reader), SERD_BLANK, "", 0);
+ if (ref) {
+ set_blank_id(reader, ref, genid_size(reader));
+ }
return ref;
}
-Ref
+SerdNode*
push_node_padded(SerdReader* const reader,
const size_t maxlen,
const SerdNodeType type,
@@ -68,6 +72,10 @@ push_node_padded(SerdReader* const reader,
void* mem = serd_stack_push_aligned(
&reader->stack, sizeof(SerdNode) + maxlen + 1, sizeof(SerdNode));
+ if (!mem) {
+ return NULL;
+ }
+
SerdNode* const node = (SerdNode*)mem;
node->length = length;
@@ -78,14 +86,15 @@ push_node_padded(SerdReader* const reader,
memcpy(buf, str, length + 1);
#ifdef SERD_STACK_CHECK
- reader->allocs = (Ref*)realloc(reader->allocs,
- sizeof(reader->allocs) * (++reader->n_allocs));
- reader->allocs[reader->n_allocs - 1] = ((char*)mem - reader->stack.buf);
+ 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 (Ref)((char*)node - reader->stack.buf);
+ return node;
}
-Ref
+SerdNode*
push_node(SerdReader* const reader,
const SerdNodeType type,
const char* const str,
@@ -94,42 +103,33 @@ push_node(SerdReader* const reader,
return push_node_padded(reader, length, type, str, length);
}
-SERD_PURE_FUNC SerdNode*
-deref(SerdReader* const reader, const Ref ref)
-{
- return ref ? (SerdNode*)(reader->stack.buf + ref) : NULL;
-}
-
-Ref
-pop_node(SerdReader* const reader, const Ref ref)
+SerdNode*
+pop_node(SerdReader* const reader, const SerdNode* const node)
{
- if (ref && ref != reader->rdf_first && ref != reader->rdf_rest &&
- ref != reader->rdf_nil) {
+ if (node && node != reader->rdf_first && node != reader->rdf_rest &&
+ node != reader->rdf_nil) {
#ifdef SERD_STACK_CHECK
- SERD_STACK_ASSERT_TOP(reader, ref);
+ SERD_STACK_ASSERT_TOP(reader, node);
--reader->n_allocs;
#endif
- SerdNode* const node = deref(reader, ref);
- char* const top = reader->stack.buf + reader->stack.size;
+ char* const top = reader->stack.buf + reader->stack.size;
serd_stack_pop_aligned(&reader->stack, (size_t)(top - (char*)node));
}
- return 0;
+ return NULL;
}
SerdStatus
-emit_statement(SerdReader* const reader, const ReadContext ctx, const Ref o)
+emit_statement(SerdReader* const reader,
+ const ReadContext ctx,
+ SerdNode* const o)
{
- SerdNode* graph = deref(reader, ctx.graph);
+ SerdNode* graph = ctx.graph;
if (!graph && reader->default_graph) {
graph = reader->default_graph;
}
- const SerdStatus st = serd_sink_write(reader->sink,
- *ctx.flags,
- deref(reader, ctx.subject),
- deref(reader, ctx.predicate),
- deref(reader, o),
- graph);
+ const SerdStatus st = serd_sink_write(
+ reader->sink, *ctx.flags, ctx.subject, ctx.predicate, o, graph);
*ctx.flags &= SERD_ANON_CONT | SERD_LIST_CONT; // Preserve only cont flags
return st;
@@ -150,21 +150,35 @@ serd_reader_read_document(SerdReader* const reader)
}
SerdReader*
-serd_reader_new(const SerdSyntax syntax, const SerdSink* const sink)
+serd_reader_new(const SerdSyntax syntax,
+ const SerdSink* const sink,
+ const size_t stack_size)
{
+ if (stack_size < 3 * sizeof(SerdNode) + 192 + serd_node_align) {
+ return NULL;
+ }
+
SerdReader* me = (SerdReader*)calloc(1, sizeof(SerdReader));
me->sink = sink;
me->default_graph = NULL;
- me->stack = serd_stack_new(SERD_PAGE_SIZE);
+ me->stack = serd_stack_new(stack_size);
me->syntax = syntax;
me->next_id = 1;
me->strict = true;
+ // Reserve a bit of space at the end of the stack to zero pad nodes
+ me->stack.buf_size -= serd_node_align;
+
me->rdf_first = push_node(me, SERD_URI, NS_RDF "first", 48);
me->rdf_rest = push_node(me, SERD_URI, NS_RDF "rest", 47);
me->rdf_nil = push_node(me, SERD_URI, NS_RDF "nil", 46);
+ // The initial stack size check should cover this
+ assert(me->rdf_first);
+ assert(me->rdf_rest);
+ assert(me->rdf_nil);
+
return me;
}