From 7ffa2c0488fcd96c3c12713e5650633eb03e91f7 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 27 Mar 2023 05:39:26 -0400 Subject: [WIP] Move SerdEnv mutation from writer to reader Writing having side-effects seems questionable in general, and this prepares things for expanding URIs in the reader. --- include/serd/reader.h | 2 ++ include/serd/writer.h | 2 +- src/read_turtle.c | 7 +++++++ src/reader.c | 3 +++ src/reader.h | 2 ++ src/writer.c | 21 ++++++++------------ test/test_overflow.c | 4 +++- test/test_reader.c | 49 +++++++++++++++++++++++++++++++++++------------ test/test_reader_writer.c | 11 ++++++++--- test/test_writer.c | 32 ------------------------------- tools/serd-pipe.c | 9 +++++---- 11 files changed, 76 insertions(+), 66 deletions(-) diff --git a/include/serd/reader.h b/include/serd/reader.h index 040f3398..658193fb 100644 --- a/include/serd/reader.h +++ b/include/serd/reader.h @@ -5,6 +5,7 @@ #define SERD_READER_H #include "serd/attributes.h" +#include "serd/env.h" #include "serd/input_stream.h" #include "serd/node.h" #include "serd/sink.h" @@ -41,6 +42,7 @@ SERD_API SerdReader* ZIX_ALLOCATED serd_reader_new(SerdWorld* ZIX_NONNULL world, SerdSyntax syntax, SerdReaderFlags flags, + SerdEnv* ZIX_NONNULL env, const SerdSink* ZIX_NONNULL sink); /** diff --git a/include/serd/writer.h b/include/serd/writer.h index 41ffb8cd..b85c7b82 100644 --- a/include/serd/writer.h +++ b/include/serd/writer.h @@ -51,7 +51,7 @@ SERD_API SerdWriter* ZIX_ALLOCATED serd_writer_new(SerdWorld* ZIX_NONNULL world, SerdSyntax syntax, SerdWriterFlags flags, - SerdEnv* ZIX_NONNULL env, + const SerdEnv* ZIX_NONNULL env, SerdOutputStream* ZIX_NONNULL output, size_t block_size); diff --git a/src/read_turtle.c b/src/read_turtle.c index 22269741..8d9ec78a 100644 --- a/src/read_turtle.c +++ b/src/read_turtle.c @@ -14,6 +14,7 @@ #include "turtle.h" #include "serd/caret.h" +#include "serd/env.h" #include "serd/node.h" #include "serd/reader.h" #include "serd/sink.h" @@ -891,6 +892,7 @@ read_turtle_base(SerdReader* const reader, const bool sparql, const bool token) } serd_node_zero_pad(uri); + TRY(st, serd_env_set_base_uri(reader->env, serd_node_string_view(uri))); TRY(st, serd_sink_write_base(reader->sink, uri)); read_turtle_ws_star(reader); @@ -934,6 +936,11 @@ read_turtle_prefixID(SerdReader* const reader, serd_node_zero_pad(name); serd_node_zero_pad(uri); + + TRY(st, + serd_env_set_prefix( + reader->env, serd_node_string_view(name), serd_node_string_view(uri))); + st = serd_sink_write_prefix(reader->sink, name, uri); if (!sparql) { diff --git a/src/reader.c b/src/reader.c index 7e0864cc..8b74836f 100644 --- a/src/reader.c +++ b/src/reader.c @@ -229,9 +229,11 @@ SerdReader* serd_reader_new(SerdWorld* const world, const SerdSyntax syntax, const SerdReaderFlags flags, + SerdEnv* const env, const SerdSink* const sink) { assert(world); + assert(env); assert(sink); const size_t stack_size = world->limits.reader_stack_size; @@ -243,6 +245,7 @@ serd_reader_new(SerdWorld* const world, me->world = world; me->sink = sink; + me->env = env; me->stack = serd_stack_new(stack_size, serd_node_align); me->syntax = syntax; me->flags = flags; diff --git a/src/reader.h b/src/reader.h index 132d038e..302f8c6f 100644 --- a/src/reader.h +++ b/src/reader.h @@ -11,6 +11,7 @@ #include "serd/attributes.h" #include "serd/caret.h" +#include "serd/env.h" #include "serd/node.h" #include "serd/reader.h" #include "serd/sink.h" @@ -40,6 +41,7 @@ struct SerdReaderImpl { SerdNode* rdf_rest; SerdNode* rdf_nil; SerdByteSource* source; + SerdEnv* env; SerdStack stack; SerdSyntax syntax; SerdReaderFlags flags; diff --git a/src/writer.c b/src/writer.c index 329a29ad..05be0500 100644 --- a/src/writer.c +++ b/src/writer.c @@ -131,7 +131,7 @@ struct SerdWriterImpl { SerdSink iface; SerdSyntax syntax; SerdWriterFlags flags; - SerdEnv* env; + const SerdEnv* env; SerdNode* root_node; SerdURIView root_uri; WriteContext* anon_stack; @@ -1367,7 +1367,7 @@ SerdWriter* serd_writer_new(SerdWorld* world, SerdSyntax syntax, SerdWriterFlags flags, - SerdEnv* env, + const SerdEnv* env, SerdOutputStream* output, size_t block_size) { @@ -1426,20 +1426,15 @@ serd_writer_set_base_uri(SerdWriter* writer, const SerdNode* uri) { assert(writer); + SerdStatus st = SERD_SUCCESS; + if (uri && serd_node_type(uri) != SERD_URI) { return SERD_BAD_ARG; } - if (serd_node_equals(serd_env_base_uri(writer->env), uri)) { - return SERD_SUCCESS; - } - const SerdStringView uri_string = uri ? serd_node_string_view(uri) : serd_empty_string(); - SerdStatus st = SERD_SUCCESS; - TRY(st, serd_env_set_base_uri(writer->env, uri_string)); - if (uri && (writer->syntax == SERD_TURTLE || writer->syntax == SERD_TRIG)) { TRY(st, terminate_context(writer)); TRY(st, esink("@base <", 7, writer)); @@ -1476,16 +1471,16 @@ serd_writer_set_prefix(SerdWriter* writer, { SerdStatus st = SERD_SUCCESS; - TRY(st, - serd_env_set_prefix( - writer->env, serd_node_string_view(name), serd_node_string_view(uri))); + if (name->type != SERD_LITERAL || uri->type != SERD_URI) { + return SERD_BAD_ARG; + } if (writer->syntax == SERD_TURTLE || writer->syntax == SERD_TRIG) { TRY(st, terminate_context(writer)); TRY(st, esink("@prefix ", 8, writer)); TRY(st, esink(serd_node_string(name), name->length, writer)); TRY(st, esink(": <", 3, writer)); - TRY(st, ewrite_uri(writer, serd_node_string(uri), uri->length)); + TRY(st, write_uri_from_node(writer, uri)); TRY(st, esink(">", 1, writer)); writer->last_sep = SEP_NODE; TRY(st, write_sep(writer, writer->context.flags, SEP_END_DIRECT)); diff --git a/test/test_overflow.c b/test/test_overflow.c index b81d4367..db20f734 100644 --- a/test/test_overflow.c +++ b/test/test_overflow.c @@ -23,7 +23,8 @@ test_size(SerdWorld* const world, serd_world_set_limits(world, limits); SerdSink* sink = serd_sink_new(NULL, NULL, NULL); - SerdReader* const reader = serd_reader_new(world, syntax, flags, sink); + SerdEnv* const env = serd_env_new(serd_empty_string()); + SerdReader* const reader = serd_reader_new(world, syntax, flags, env, sink); if (!reader) { return SERD_BAD_STACK; } @@ -38,6 +39,7 @@ test_size(SerdWorld* const world, serd_close_input(&in); serd_node_free(string_name); serd_reader_free(reader); + serd_env_free(env); serd_sink_free(sink); return st; diff --git a/test/test_reader.c b/test/test_reader.c index b5cefbe1..f1ec1d35 100644 --- a/test/test_reader.c +++ b/test/test_reader.c @@ -4,6 +4,7 @@ #undef NDEBUG #include "serd/caret.h" +#include "serd/env.h" #include "serd/event.h" #include "serd/input_stream.h" #include "serd/node.h" @@ -96,7 +97,9 @@ test_prepare_error(const char* const path) SerdSink* const sink = serd_sink_new(&rt, test_sink, NULL); assert(sink); - SerdReader* const reader = serd_reader_new(world, SERD_TURTLE, 0, sink); + SerdEnv* const env = serd_env_new(serd_empty_string()); + SerdReader* const reader = serd_reader_new(world, SERD_TURTLE, 0, env, sink); + assert(reader); SerdInputStream in = @@ -111,6 +114,7 @@ test_prepare_error(const char* const path) serd_close_input(&in); serd_reader_free(reader); + serd_env_free(env); serd_sink_free(sink); serd_world_free(world); fclose(f); @@ -125,7 +129,9 @@ test_read_string(void) SerdSink* sink = serd_sink_new(&rt, test_sink, NULL); assert(sink); - SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, sink); + SerdEnv* const env = serd_env_new(serd_empty_string()); + SerdReader* const reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink); + assert(reader); static const char* const string1 = @@ -162,6 +168,7 @@ test_read_string(void) assert(!serd_close_input(&in)); serd_reader_free(reader); + serd_env_free(env); serd_sink_free(sink); serd_world_free(world); } @@ -221,11 +228,11 @@ test_read_eof_by_page(const char* const path) fflush(f); fseek(f, 0L, SEEK_SET); - SerdWorld* world = serd_world_new(); - ReaderTest ignored = {0, 0, 0, 0}; - SerdSink* sink = serd_sink_new(&ignored, test_sink, NULL); - SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, sink); - + SerdWorld* world = serd_world_new(); + ReaderTest ignored = {0, 0, 0, 0}; + SerdSink* sink = serd_sink_new(&ignored, test_sink, NULL); + SerdEnv* env = serd_env_new(serd_empty_string()); + SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink); SerdInputStream in = serd_open_input_stream((SerdReadFunc)fread, (SerdErrorFunc)ferror, NULL, f); @@ -237,6 +244,7 @@ test_read_eof_by_page(const char* const path) assert(!serd_close_input(&in)); serd_reader_free(reader); + serd_env_free(env); serd_sink_free(sink); serd_world_free(world); fclose(f); @@ -250,7 +258,8 @@ test_read_eof_by_byte(void) SerdWorld* world = serd_world_new(); ReaderTest ignored = {0, 0, 0, 0}; SerdSink* sink = serd_sink_new(&ignored, test_sink, NULL); - SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, sink); + SerdEnv* env = serd_env_new(serd_empty_string()); + SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink); size_t n_reads = 0U; SerdInputStream in = serd_open_input_stream( @@ -265,6 +274,7 @@ test_read_eof_by_byte(void) assert(!serd_close_input(&in)); serd_reader_free(reader); + serd_env_free(env); serd_sink_free(sink); serd_world_free(world); } @@ -300,7 +310,10 @@ test_read_nquads_chunks(const char* const path) SerdSink* const sink = serd_sink_new(&rt, test_sink, NULL); assert(sink); - SerdReader* const reader = serd_reader_new(world, SERD_NQUADS, 0U, sink); + SerdEnv* const env = serd_env_new(serd_empty_string()); + assert(env); + + SerdReader* const reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink); assert(reader); SerdInputStream in = @@ -353,6 +366,7 @@ test_read_nquads_chunks(const char* const path) assert(!serd_close_input(&in)); serd_reader_free(reader); + serd_env_free(env); serd_sink_free(sink); serd_world_free(world); fclose(f); @@ -382,7 +396,10 @@ test_read_turtle_chunks(const char* const path) SerdSink* sink = serd_sink_new(&rt, test_sink, NULL); assert(sink); - SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, sink); + SerdEnv* const env = serd_env_new(serd_empty_string()); + assert(env); + + SerdReader* const reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink); assert(reader); SerdInputStream in = @@ -451,6 +468,7 @@ test_read_turtle_chunks(const char* const path) assert(!serd_close_input(&in)); serd_reader_free(reader); + serd_env_free(env); serd_sink_free(sink); serd_world_free(world); fclose(f); @@ -467,7 +485,11 @@ test_read_empty(const char* const path) SerdSink* const sink = serd_sink_new(&rt, test_sink, NULL); assert(sink); - SerdReader* const reader = serd_reader_new(world, SERD_SYNTAX_EMPTY, 0, sink); + SerdEnv* const env = serd_env_new(serd_empty_string()); + assert(env); + + SerdReader* const reader = + serd_reader_new(world, SERD_SYNTAX_EMPTY, 0U, env, sink); assert(reader); FILE* const f = fopen(path, "w+b"); @@ -487,6 +509,7 @@ test_read_empty(const char* const path) fclose(f); assert(!zix_remove(path)); serd_reader_free(reader); + serd_env_free(env); serd_sink_free(sink); serd_world_free(world); } @@ -516,7 +539,8 @@ test_error_cursor(void) SerdWorld* world = serd_world_new(); bool called = false; SerdSink* sink = serd_sink_new(&called, check_cursor, NULL); - SerdReader* const reader = serd_reader_new(world, SERD_TURTLE, 0, sink); + SerdEnv* const env = serd_env_new(serd_empty_string()); + SerdReader* const reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink); assert(sink); assert(reader); @@ -537,6 +561,7 @@ test_error_cursor(void) serd_node_free(string_name); serd_reader_free(reader); + serd_env_free(env); serd_sink_free(sink); serd_world_free(world); } diff --git a/test/test_reader_writer.c b/test/test_reader_writer.c index df2c3957..3a20bb7a 100644 --- a/test/test_reader_writer.c +++ b/test/test_reader_writer.c @@ -117,7 +117,8 @@ test_write_errors(void) serd_writer_new(world, syntax, 0U, env, &out, 1U); const SerdSink* const sink = serd_writer_sink(writer); - SerdReader* const reader = serd_reader_new(world, SERD_TRIG, 0U, sink); + SerdReader* const reader = + serd_reader_new(world, SERD_TRIG, 0U, env, sink); const char* position = doc_string; SerdInputStream in = serd_open_input_string(&position); @@ -251,16 +252,19 @@ test_reader(const char* path) SerdSink* const sink = serd_sink_new(&rt, test_sink, NULL); assert(sink); + SerdEnv* const env = serd_env_new(serd_empty_string()); + assert(env); + // Test that too little stack space fails gracefully const SerdLimits old_limits = serd_world_limits(world); SerdLimits limits = old_limits; limits.reader_stack_size = 32U; serd_world_set_limits(world, limits); - assert(!serd_reader_new(world, SERD_TURTLE, 0U, sink)); + assert(!serd_reader_new(world, SERD_TURTLE, 0U, env, sink)); // Restore limits and successfully create reader serd_world_set_limits(world, old_limits); - SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, sink); + SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink); assert(reader); assert(serd_reader_read_chunk(reader) == SERD_BAD_CALL); @@ -285,6 +289,7 @@ test_reader(const char* path) serd_close_input(&in); serd_reader_free(reader); + serd_env_free(env); serd_sink_free(sink); serd_world_free(world); } diff --git a/test/test_writer.c b/test/test_writer.c index 9ce69c55..f76cc800 100644 --- a/test/test_writer.c +++ b/test/test_writer.c @@ -65,37 +65,6 @@ test_write_bad_event(void) serd_world_free(world); } -static void -test_write_bad_prefix(void) -{ - SerdWorld* world = serd_world_new(); - SerdEnv* env = serd_env_new(serd_empty_string()); - SerdBuffer buffer = {NULL, 0}; - SerdOutputStream output = serd_open_output_buffer(&buffer); - SerdWriter* writer = - serd_writer_new(world, SERD_TURTLE, 0U, env, &output, 1U); - - assert(writer); - - SerdNode* name = serd_new_string(serd_string("eg")); - SerdNode* uri = serd_new_uri(serd_string("rel")); - - assert(serd_sink_write_prefix(serd_writer_sink(writer), name, uri) == - SERD_BAD_ARG); - - serd_buffer_close(&buffer); - - char* const out = (char*)buffer.buf; - assert(!strcmp(out, "")); - serd_free(out); - - serd_node_free(uri); - serd_node_free(name); - serd_writer_free(writer); - serd_env_free(env); - serd_world_free(world); -} - static void test_write_long_literal(void) { @@ -442,7 +411,6 @@ main(void) { test_writer_new(); test_write_bad_event(); - test_write_bad_prefix(); test_write_long_literal(); test_writer_cleanup(); test_strict_write(); diff --git a/tools/serd-pipe.c b/tools/serd-pipe.c index 734d02f4..8bf26f2a 100644 --- a/tools/serd-pipe.c +++ b/tools/serd-pipe.c @@ -72,6 +72,7 @@ static SerdStatus read_file(SerdWorld* const world, const SerdSyntax syntax, const SerdReaderFlags flags, + SerdEnv* const env, const SerdSink* const sink, const size_t stack_size, const char* const filename, @@ -86,12 +87,10 @@ read_file(SerdWorld* const world, return SERD_BAD_STREAM; } - SerdLimits limits = serd_world_limits(world); - limits.reader_stack_size = stack_size; + const SerdLimits limits = {stack_size, MAX_DEPTH}; serd_world_set_limits(world, limits); - SerdReader* reader = serd_reader_new(world, syntax, flags, sink); - + SerdReader* reader = serd_reader_new(world, syntax, flags, env, sink); serd_reader_add_blank_prefix(reader, add_prefix); SerdStatus st = serd_reader_start(reader, &in, NULL, block_size); @@ -315,6 +314,7 @@ main(int argc, char** argv) serd_reader_new(world, input_syntax ? input_syntax : SERD_TRIG, reader_flags, + env, serd_writer_sink(writer)); serd_reader_add_blank_prefix(reader, add_prefix); @@ -349,6 +349,7 @@ main(int argc, char** argv) if ((st = read_file(world, serd_choose_syntax(world, input_syntax, inputs[i]), reader_flags, + env, serd_writer_sink(writer), stack_size, inputs[i], -- cgit v1.2.1