From 059b4764d6b6b3a9ef04600bda45815c69365d30 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 29 May 2021 15:20:23 -0400 Subject: Use a manual type-safe stack in writer This fixes alignment issues on ARM. Since this stack is just for WriteContext which has a fixed size, using SerdStack here just made things more confusing anyway. --- meson.build | 2 -- src/writer.c | 66 ++++++++++++++++++++++++++---------------------------------- 2 files changed, 28 insertions(+), 40 deletions(-) diff --git a/meson.build b/meson.build index dcca40b1..90f59e9b 100644 --- a/meson.build +++ b/meson.build @@ -29,7 +29,6 @@ if get_option('strict') if cc.get_id() == 'clang' c_suppressions += [ - '-Wno-cast-align', '-Wno-format-nonliteral', '-Wno-nullability-extension', '-Wno-nullable-to-nonnull-conversion', @@ -38,7 +37,6 @@ if get_option('strict') ] elif cc.get_id() == 'gcc' c_suppressions += [ - '-Wno-cast-align', '-Wno-float-conversion', # MinGW '-Wno-format-nonliteral', '-Wno-inline', diff --git a/src/writer.c b/src/writer.c index 2b1bc39d..cd6ce613 100644 --- a/src/writer.c +++ b/src/writer.c @@ -18,7 +18,6 @@ #include "node.h" #include "serd_internal.h" #include "sink.h" -#include "stack.h" #include "string_utils.h" #include "system.h" #include "uri_utils.h" @@ -65,6 +64,8 @@ typedef struct { static const WriteContext WRITE_CONTEXT_NULL = {CTX_NAMED, 0, NULL, NULL, NULL, false}; +static const size_t anon_stack_capacity = SERD_PAGE_SIZE / sizeof(WriteContext); + typedef enum { SEP_NONE, ///< Placeholder for nodes or nothing SEP_END_S, ///< End of a subject ('.') @@ -127,7 +128,8 @@ struct SerdWriterImpl { SerdEnv* env; SerdNode* root_node; SerdURIView root_uri; - SerdStack anon_stack; + WriteContext* anon_stack; + size_t anon_stack_size; SerdWriteFunc write_func; void* stream; WriteContext context; @@ -180,15 +182,10 @@ push_context(SerdWriter* const writer, const SerdNode* const s, const SerdNode* const p) { - WriteContext* top = - (WriteContext*)serd_stack_push(&writer->anon_stack, sizeof(WriteContext)); - - if (!top) { + if (writer->anon_stack_size >= anon_stack_capacity) { return SERD_ERR_OVERFLOW; } - *top = writer->context; - const WriteContext new_context = {type, flags, serd_node_copy(g), @@ -196,21 +193,18 @@ push_context(SerdWriter* const writer, serd_node_copy(p), false}; - writer->context = new_context; + writer->anon_stack[writer->anon_stack_size++] = writer->context; + writer->context = new_context; return SERD_SUCCESS; } static void pop_context(SerdWriter* writer) { - assert(!serd_stack_is_empty(&writer->anon_stack)); + assert(writer->anon_stack_size > 0); free_context(writer); - writer->context = - *(WriteContext*)(writer->anon_stack.buf + writer->anon_stack.size - - sizeof(WriteContext)); - - serd_stack_pop(&writer->anon_stack, sizeof(WriteContext)); + writer->context = writer->anon_stack[--writer->anon_stack_size]; } static SerdNode* @@ -635,7 +629,7 @@ static void reset_context(SerdWriter* writer, bool graph) { // Free any lingering contexts in case there was an error - while (!serd_stack_is_empty(&writer->anon_stack)) { + while (writer->anon_stack_size > 0) { pop_context(writer); } @@ -651,10 +645,9 @@ reset_context(SerdWriter* writer, bool graph) memset(writer->context.predicate, 0, sizeof(SerdNode)); } + writer->anon_stack_size = 0; writer->context.indented_object = false; writer->empty = false; - - serd_stack_clear(&writer->anon_stack); } static bool @@ -1015,26 +1008,21 @@ serd_writer_write_statement(SerdWriter* const writer, writer->context.indented_object = false; } - if (serd_stack_is_empty(&writer->anon_stack)) { - if (ctx(writer, SERD_SUBJECT)) { // Terminate last subject - TRY(st, write_sep(writer, writer->context.flags, SEP_END_S)); - } - TRY(st, write_top_level_sep(writer)); - } - - if (serd_stack_is_empty(&writer->anon_stack)) { - TRY(st, write_node(writer, subject, SERD_SUBJECT, flags)); - if (!(flags & (SERD_ANON_S | SERD_LIST_S))) { - TRY(st, write_sep(writer, writer->context.flags, SEP_S_P)); - } else if (flags & SERD_ANON_S) { - TRY(st, write_sep(writer, writer->context.flags, SEP_ANON_S_P)); - } - } else { - TRY(st, write_sep(writer, writer->context.flags, SEP_ANON_S_P)); + if (ctx(writer, SERD_SUBJECT)) { + // Terminate last subject + TRY(st, write_sep(writer, writer->context.flags, SEP_END_S)); } + // Start new subject + TRY(st, write_top_level_sep(writer)); reset_context(writer, false); serd_node_set(&writer->context.subject, subject); + TRY(st, write_node(writer, subject, SERD_SUBJECT, flags)); + if (!(flags & (SERD_ANON_S | SERD_LIST_S))) { + TRY(st, write_sep(writer, writer->context.flags, SEP_S_P)); + } else if (flags & SERD_ANON_S) { + TRY(st, write_sep(writer, writer->context.flags, SEP_ANON_S_P)); + } if (!(flags & SERD_LIST_S)) { TRY(st, write_pred(writer, flags, predicate)); @@ -1080,7 +1068,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 == 0) { return serd_world_errorf(writer->world, SERD_ERR_UNKNOWN, "unexpected end of anonymous node `%s'\n", @@ -1131,7 +1119,7 @@ serd_writer_finish(SerdWriter* writer) } // Free any lingering contexts in case there was an error - while (!serd_stack_is_empty(&writer->anon_stack)) { + while (writer->anon_stack_size > 0) { pop_context(writer); } @@ -1159,12 +1147,14 @@ serd_writer_new(SerdWorld* world, writer->env = env; writer->root_node = NULL; writer->root_uri = SERD_URI_NULL; - writer->anon_stack = serd_stack_new(SERD_PAGE_SIZE); writer->write_func = write_func; writer->stream = stream; writer->context = context; writer->empty = true; + writer->anon_stack = + (WriteContext*)calloc(anon_stack_capacity, sizeof(WriteContext)); + writer->iface.handle = writer; writer->iface.on_event = (SerdEventFunc)serd_writer_on_event; @@ -1269,7 +1259,7 @@ serd_writer_free(SerdWriter* writer) } serd_writer_finish(writer); - serd_stack_free(&writer->anon_stack); + free(writer->anon_stack); free(writer->bprefix); serd_node_free(writer->root_node); free(writer); -- cgit v1.2.1