diff options
author | David Robillard <d@drobilla.net> | 2021-07-08 16:15:46 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 16:27:02 -0500 |
commit | fb95ceca3b744e47e973585aa682515365ac9eb0 (patch) | |
tree | 264e30801d634ea580478a10095938448b4962c8 /src/reader.c | |
parent | 8978501e5cf06f366eb14f6ef5f5f7f2f8e34986 (diff) | |
download | serd-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.c | 84 |
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; } |