aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/serdi.c4
-rw-r--r--src/stack.h6
-rw-r--r--src/world.c1
-rw-r--r--src/writer.c84
4 files changed, 46 insertions, 49 deletions
diff --git a/src/serdi.c b/src/serdi.c
index 105bda46..75599ac7 100644
--- a/src/serdi.c
+++ b/src/serdi.c
@@ -32,6 +32,8 @@
#define SERDI_ERROR(msg) fprintf(stderr, "serdi: " msg)
#define SERDI_ERRORF(fmt, ...) fprintf(stderr, "serdi: " fmt, __VA_ARGS__)
+#define MAX_DEPTH 128U
+
static int
print_version(void)
{
@@ -245,7 +247,7 @@ main(int argc, char** argv)
SerdWriter* const writer = serd_writer_new(
world, output_syntax, writer_flags, env, (SerdWriteFunc)fwrite, out_fd);
- const SerdLimits limits = {stack_size};
+ const SerdLimits limits = {stack_size, MAX_DEPTH};
serd_world_set_limits(world, limits);
SerdReader* const reader =
diff --git a/src/stack.h b/src/stack.h
index 6ad3385d..cdf2b0f6 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -33,12 +33,6 @@ serd_stack_new(size_t size)
return stack;
}
-static inline bool
-serd_stack_is_empty(const SerdStack* stack)
-{
- return stack->size <= SERD_STACK_BOTTOM;
-}
-
static inline void
serd_stack_free(SerdStack* stack)
{
diff --git a/src/world.c b/src/world.c
index 7fb5eea2..dcf0b6af 100644
--- a/src/world.c
+++ b/src/world.c
@@ -104,6 +104,7 @@ serd_world_new(void)
}
world->limits.reader_stack_size = 1048576U;
+ world->limits.writer_max_depth = 128U;
world->blank_node = blank_node;
return world;
diff --git a/src/writer.c b/src/writer.c
index 58fd0d53..5603e9ca 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -6,7 +6,6 @@
#include "node.h"
#include "serd_internal.h"
#include "sink.h"
-#include "stack.h"
#include "string_utils.h"
#include "system.h"
#include "try.h"
@@ -134,7 +133,9 @@ struct SerdWriterImpl {
SerdEnv* env;
SerdNode* root_node;
SerdURIView root_uri;
- SerdStack anon_stack;
+ WriteContext* anon_stack;
+ size_t max_depth;
+ size_t anon_stack_size;
SerdByteSink byte_sink;
WriteContext context;
char* bprefix;
@@ -223,12 +224,12 @@ push_context(SerdWriter* const writer,
const SerdNode* const predicate)
{
// Push the current context to the stack
- void* const top = serd_stack_push(&writer->anon_stack, sizeof(WriteContext));
- if (!top) {
+
+ if (writer->anon_stack_size >= writer->max_depth) {
return SERD_BAD_STACK;
}
- *(WriteContext*)top = writer->context;
+ writer->anon_stack[writer->anon_stack_size++] = writer->context;
// Update the current context
@@ -247,14 +248,10 @@ push_context(SerdWriter* const writer,
static void
pop_context(SerdWriter* writer)
{
- // Replace the current context with the top of the stack
- free_context(&writer->context);
- writer->context =
- *(WriteContext*)(writer->anon_stack.buf + writer->anon_stack.size -
- sizeof(WriteContext));
+ assert(writer->anon_stack_size > 0);
- // Pop the top of the stack away
- serd_stack_pop(&writer->anon_stack, sizeof(WriteContext));
+ free_context(&writer->context);
+ writer->context = writer->anon_stack[--writer->anon_stack_size];
}
SERD_NODISCARD static size_t
@@ -678,7 +675,7 @@ write_sep(SerdWriter* writer, const SerdStatementFlags flags, Sep sep)
static void
free_anon_stack(SerdWriter* writer)
{
- while (!serd_stack_is_empty(&writer->anon_stack)) {
+ while (writer->anon_stack_size > 0) {
pop_context(writer);
}
}
@@ -706,6 +703,7 @@ reset_context(SerdWriter* writer, const unsigned flags)
writer->indent = 0;
}
+ writer->anon_stack_size = 0;
writer->context.type = CTX_NAMED;
writer->context.predicates = false;
writer->context.comma_indented = false;
@@ -1093,29 +1091,26 @@ serd_writer_write_statement(SerdWriter* const writer,
} else {
// No abbreviation
- if (serd_stack_is_empty(&writer->anon_stack)) {
- if (ctx(writer, SERD_SUBJECT)) {
- TRY(st, write_sep(writer, flags, SEP_END_S));
- }
- if (writer->last_sep == SEP_END_S || writer->last_sep == SEP_END_DIRECT) {
- TRY(st, write_top_level_sep(writer));
- }
+ if (ctx(writer, SERD_SUBJECT)) {
+ TRY(st, write_sep(writer, flags, SEP_END_S));
+ }
- TRY(st, write_node(writer, subject, SERD_SUBJECT, flags));
- if ((flags & (SERD_ANON_S | SERD_LIST_S))) {
- TRY(st, write_sep(writer, flags, SEP_ANON_S_P));
- } else {
- TRY(st, write_sep(writer, flags, SEP_S_P));
- }
+ if (writer->last_sep == SEP_END_S || writer->last_sep == SEP_END_DIRECT) {
+ TRY(st, write_top_level_sep(writer));
+ }
- } else {
+ // Write subject node
+ TRY(st, write_node(writer, subject, SERD_SUBJECT, flags));
+ if (!(flags & (SERD_ANON_S | SERD_LIST_S))) {
+ TRY(st, write_sep(writer, flags, SEP_S_P));
+ } else if (flags & SERD_ANON_S) {
TRY(st, write_sep(writer, flags, SEP_ANON_S_P));
}
+ // Set context to new subject and write predicate
reset_context(writer, 0U);
serd_node_set(&writer->context.subject, subject);
-
if (!(flags & SERD_LIST_S)) {
TRY(st, write_pred(writer, flags, predicate));
}
@@ -1158,7 +1153,7 @@ serd_writer_end_anon(SerdWriter* writer, const SerdNode* node)
return SERD_SUCCESS;
}
- if (serd_stack_is_empty(&writer->anon_stack)) {
+ if (!writer->anon_stack_size) {
return w_err(writer, SERD_BAD_EVENT, "unexpected end of anonymous node\n");
}
@@ -1214,20 +1209,25 @@ serd_writer_new(SerdWorld* world,
SerdWriteFunc ssink,
void* stream)
{
- const WriteContext context = WRITE_CONTEXT_NULL;
- SerdWriter* writer = (SerdWriter*)calloc(1, sizeof(SerdWriter));
-
- writer->world = world;
- writer->syntax = syntax;
- writer->flags = flags;
- writer->env = env;
- writer->root_node = NULL;
- writer->root_uri = SERD_URI_NULL;
- writer->anon_stack = serd_stack_new(SERD_PAGE_SIZE);
- writer->context = context;
- writer->byte_sink = serd_byte_sink_new(
+ const size_t max_depth = world->limits.writer_max_depth;
+ const WriteContext context = WRITE_CONTEXT_NULL;
+ SerdWriter* writer = (SerdWriter*)calloc(1, sizeof(SerdWriter));
+
+ writer->world = world;
+ writer->syntax = syntax;
+ writer->flags = flags;
+ writer->env = env;
+ writer->root_node = NULL;
+ writer->root_uri = SERD_URI_NULL;
+ writer->context = context;
+ writer->byte_sink = serd_byte_sink_new(
ssink, stream, (flags & SERD_WRITE_BULK) ? SERD_PAGE_SIZE : 1);
+ if (max_depth) {
+ writer->max_depth = max_depth;
+ writer->anon_stack = (WriteContext*)calloc(max_depth, sizeof(WriteContext));
+ }
+
writer->iface.handle = writer;
writer->iface.on_event = (SerdEventFunc)serd_writer_on_event;
@@ -1328,7 +1328,7 @@ serd_writer_free(SerdWriter* writer)
serd_writer_finish(writer);
free_context(&writer->context);
free_anon_stack(writer);
- serd_stack_free(&writer->anon_stack);
+ free(writer->anon_stack);
free(writer->bprefix);
serd_byte_sink_free(&writer->byte_sink);
serd_node_free(writer->root_node);