aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-06-14 12:23:43 +0200
committerDavid Robillard <d@drobilla.net>2020-06-21 18:12:04 +0200
commitf9a3ef354799f664edee2e2f31c59f1a3f8ccdff (patch)
tree93414bb184909ee75dee4e4f20bddcfd2bca43da
parent09e86bcf3e337f5a8e5da4a1779faf26d29e0c72 (diff)
downloadserd-f9a3ef354799f664edee2e2f31c59f1a3f8ccdff.tar.gz
serd-f9a3ef354799f664edee2e2f31c59f1a3f8ccdff.tar.bz2
serd-f9a3ef354799f664edee2e2f31c59f1a3f8ccdff.zip
Use a manual type-safe stack in SerdWriter
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.
-rw-r--r--src/writer.c54
-rw-r--r--wscript3
2 files changed, 30 insertions, 27 deletions
diff --git a/src/writer.c b/src/writer.c
index e6f4653e..1a7117c3 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -17,7 +17,6 @@
#include "env.h"
#include "node.h"
#include "sink.h"
-#include "stack.h"
#include "string_utils.h"
#include "system.h"
#include "uri_utils.h"
@@ -64,6 +63,8 @@ static const WriteContext WRITE_CONTEXT_NULL = {CTX_NAMED,
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 {
SerdWriterFlags flags;
SerdNode* root_node;
SerdURI root_uri;
- SerdStack anon_stack;
+ WriteContext* anon_stack;
+ size_t anon_stack_size;
SerdWriteFunc write_func;
void* stream;
SerdLogFunc log_func;
@@ -171,7 +173,7 @@ free_context(SerdWriter* writer)
return SERD_SUCCESS;
}
-static void
+static SerdStatus
push_context(SerdWriter* const writer,
const ContextType type,
const SerdStatementFlags flags,
@@ -179,10 +181,9 @@ push_context(SerdWriter* const writer,
const SerdNode* const s,
const SerdNode* const p)
{
- WriteContext* top = (WriteContext*)serd_stack_push(&writer->anon_stack,
- sizeof(WriteContext));
-
- *top = writer->context;
+ if (writer->anon_stack_size >= anon_stack_capacity) {
+ return SERD_ERR_OVERFLOW;
+ }
const WriteContext new_context = {type,
flags,
@@ -191,24 +192,23 @@ push_context(SerdWriter* const writer,
serd_node_copy(p),
false};
+ writer->anon_stack[writer->anon_stack_size++] = writer->context;
writer->context = new_context;
+
+ return SERD_SUCCESS;
}
static inline void
pop_context(SerdWriter* writer)
{
- assert(!serd_stack_is_empty(&writer->anon_stack));
+ assert(writer->anon_stack_size > 0);
if (writer->context.indented_object && writer->indent > 0) {
--writer->indent;
}
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 inline SerdNode*
@@ -935,14 +935,14 @@ serd_writer_write_statement(SerdWriter* writer,
writer->context.indented_object = false;
}
- if (serd_stack_is_empty(&writer->anon_stack)) {
+ if (writer->anon_stack_size == 0) {
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)) {
+ if (writer->anon_stack_size == 0) {
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));
@@ -964,21 +964,21 @@ serd_writer_write_statement(SerdWriter* writer,
}
if (flags & SERD_LIST_S) {
- push_context(writer, CTX_LIST, flags, graph, subject, NULL);
+ st = push_context(writer, CTX_LIST, flags, graph, subject, NULL);
} if (flags & SERD_LIST_O) {
- push_context(writer, CTX_LIST, flags, graph, object, NULL);
+ st = push_context(writer, CTX_LIST, flags, graph, object, NULL);
}
if (flags & (SERD_ANON_S | SERD_ANON_O)) {
const bool is_list = flags & (SERD_LIST_S | SERD_LIST_O);
const bool is_subject = flags & SERD_ANON_S;
- push_context(writer,
- is_list ? CTX_LIST : CTX_BLANK,
- flags,
- graph,
- subject,
- is_subject ? predicate : NULL);
+ st = push_context(writer,
+ is_list ? CTX_LIST : CTX_BLANK,
+ flags,
+ graph,
+ subject,
+ is_subject ? predicate : NULL);
} else {
serd_node_set(&writer->context.graph, graph);
serd_node_set(&writer->context.subject, subject);
@@ -993,7 +993,7 @@ serd_writer_end_anon(SerdWriter* writer, const SerdNode* node)
{
if (writer->syntax != SERD_TURTLE && writer->syntax != SERD_TRIG) {
return SERD_SUCCESS;
- } else if (serd_stack_is_empty(&writer->anon_stack)) {
+ } else if (writer->anon_stack_size == 0) {
return SERD_LOG_ERROR(writer->world, SERD_ERR_UNKNOWN,
"unexpected end of anonymous node\n");
}
@@ -1044,7 +1044,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);
}
@@ -1070,7 +1070,7 @@ serd_writer_new(SerdWorld* world,
writer->flags = flags;
writer->root_node = NULL;
writer->root_uri = SERD_URI_NULL;
- writer->anon_stack = serd_stack_new(SERD_PAGE_SIZE);
+ writer->anon_stack = (WriteContext*)calloc(anon_stack_capacity, sizeof(WriteContext));
writer->write_func = write_func;
writer->stream = stream;
writer->context = context;
@@ -1159,7 +1159,7 @@ void
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);
diff --git a/wscript b/wscript
index f09a7207..47f709e7 100644
--- a/wscript
+++ b/wscript
@@ -62,6 +62,9 @@ def configure(conf):
conf.find_program("clang-tidy", var="CLANG_TIDY", mandatory=False)
conf.find_program("iwyu_tool", var="IWYU_TOOL", mandatory=False)
+ if Options.options.strict and not conf.env.MSVC_COMPILER:
+ conf.env.append_unique('CFLAGS', '-Wno-cast-align')
+
conf.env.update({
'BUILD_UTILS': not Options.options.no_utils,
'BUILD_SHARED': not Options.options.no_shared,