From 0e739f34801ff6810064a8fac570f6be2b61ae70 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 13 Aug 2021 20:31:57 -0400 Subject: Simplify output stream API This makes the paging mechanism an internal detail once again. While it's conceptually elegant to simply have a single write interface and have the block dumper just be another implementation of that, unfortunately it is not practical. The inlining of serd_block_dumper_write() is a significant performance boost, because it avoids a non-inlinable function call of overhead per character. Compared to the SerdByteSink approach, this removes the burden and overhead of needing to dynamically allocate the structure itself. --- test/meson.build | 1 - test/test_byte_sink.c | 32 ------------ test/test_free_null.c | 1 - test/test_model.c | 62 +++++++++++++---------- test/test_reader_writer.c | 14 +++--- test/test_terse_write.c | 8 +-- test/test_writer.c | 122 +++++++++++++++++++++++++--------------------- 7 files changed, 113 insertions(+), 127 deletions(-) delete mode 100644 test/test_byte_sink.c (limited to 'test') diff --git a/test/meson.build b/test/meson.build index c314e1d4..ab7666e3 100644 --- a/test/meson.build +++ b/test/meson.build @@ -8,7 +8,6 @@ run_sort_suite = find_program('run_sort_suite.py') wrapper = meson.get_cross_property('exe_wrapper', '') unit_tests = [ - 'byte_sink', 'byte_source', 'caret', 'cursor', diff --git a/test/test_byte_sink.c b/test/test_byte_sink.c deleted file mode 100644 index 71f1e62d..00000000 --- a/test/test_byte_sink.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright 2021 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#undef NDEBUG - -#include "serd/serd.h" - -#include -#include - -int -main(void) -{ - assert(!serd_byte_sink_new_filename("file.ttl", 0)); - assert(!serd_byte_sink_new_filename("/does/not/exist.ttl", 1)); - assert(!serd_byte_sink_new_function((SerdWriteFunc)fwrite, NULL, NULL, 0)); - - return 0; -} diff --git a/test/test_free_null.c b/test/test_free_null.c index 1fa87979..51a3c2dc 100644 --- a/test/test_free_null.c +++ b/test/test_free_null.c @@ -25,7 +25,6 @@ main(void) { serd_free(NULL); serd_byte_source_free(NULL); - serd_byte_sink_free(NULL); serd_node_free(NULL); serd_world_free(NULL); serd_env_free(NULL); diff --git a/test/test_model.c b/test/test_model.c index acefe05f..78372997 100644 --- a/test/test_model.c +++ b/test/test_model.c @@ -1052,10 +1052,12 @@ test_write_flat_range(SerdWorld* world, const unsigned n_quads) serd_model_add(model, s, p, b2, NULL); serd_model_add(model, b2, p, o, NULL); - SerdBuffer buffer = {NULL, 0}; - SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); - SerdByteSink* out = serd_byte_sink_new_buffer(&buffer); - SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0, env, out); + SerdBuffer buffer = {NULL, 0}; + SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); + SerdOutputStream out = serd_open_output_buffer(&buffer); + + SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0, env, &out, 1); + assert(writer); SerdCursor* all = serd_model_begin(model); for (const SerdStatement* t = NULL; (t = serd_cursor_get(all)); @@ -1065,7 +1067,7 @@ test_write_flat_range(SerdWorld* world, const unsigned n_quads) serd_cursor_free(all); serd_writer_finish(writer); - serd_byte_sink_close(out); + serd_close_output(&out); const char* const str = (const char*)buffer.buf; static const char* const expected = "\n" @@ -1078,11 +1080,11 @@ test_write_flat_range(SerdWorld* world, const unsigned n_quads) "_:b2\n" "\t .\n"; + assert(str); assert(!strcmp(str, expected)); - free(buffer.buf); + serd_free(buffer.buf); serd_writer_free(writer); - serd_byte_sink_free(out); serd_model_free(model); serd_env_free(env); serd_nodes_free(nodes); @@ -1121,17 +1123,19 @@ test_write_bad_list(SerdWorld* world, const unsigned n_quads) serd_model_add(model, list2, prest, norest, NULL); serd_model_add(model, norest, pfirst, val2, NULL); - SerdBuffer buffer = {NULL, 0}; - SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); - SerdByteSink* out = serd_byte_sink_new_buffer(&buffer); - SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0, env, out); + SerdBuffer buffer = {NULL, 0}; + SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); + SerdOutputStream out = serd_open_output_buffer(&buffer); + + SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0, env, &out, 1); + assert(writer); SerdCursor* all = serd_model_begin(model); serd_describe_range(all, serd_writer_sink(writer), 0); serd_cursor_free(all); serd_writer_finish(writer); - serd_byte_sink_close(out); + serd_close_output(&out); const char* str = (const char*)buffer.buf; const char* expected = "\n" @@ -1142,11 +1146,12 @@ test_write_bad_list(SerdWorld* world, const unsigned n_quads) " \"b\"\n" " ) .\n"; + assert(str); assert(!strcmp(str, expected)); free(buffer.buf); serd_writer_free(writer); - serd_byte_sink_free(out); + serd_close_output(&out); serd_model_free(model); serd_env_free(env); serd_nodes_free(nodes); @@ -1180,10 +1185,12 @@ test_write_infinite_list(SerdWorld* world, const unsigned n_quads) serd_model_add(model, list2, pfirst, val2, NULL); serd_model_add(model, list2, prest, list1, NULL); - SerdBuffer buffer = {NULL, 0}; - SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); - SerdByteSink* out = serd_byte_sink_new_buffer(&buffer); - SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0, env, out); + SerdBuffer buffer = {NULL, 0}; + SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); + SerdOutputStream out = serd_open_output_buffer(&buffer); + + SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0, env, &out, 1); + assert(writer); serd_env_set_prefix( env, @@ -1195,7 +1202,7 @@ test_write_infinite_list(SerdWorld* world, const unsigned n_quads) serd_cursor_free(all); serd_writer_finish(writer); - serd_byte_sink_close(out); + serd_close_output(&out); const char* str = (const char*)buffer.buf; const char* expected = "\n" " _:l1 .\n" @@ -1207,11 +1214,12 @@ test_write_infinite_list(SerdWorld* world, const unsigned n_quads) " rdf:rest _:l1\n" " ] .\n"; + assert(str); assert(!strcmp(str, expected)); free(buffer.buf); serd_writer_free(writer); - serd_byte_sink_free(out); + serd_close_output(&out); serd_model_free(model); serd_env_free(env); serd_nodes_free(nodes); @@ -1272,10 +1280,10 @@ test_write_error_in_list_subject(SerdWorld* world, const unsigned n_quads) for (size_t max_successes = 0; max_successes < 18; ++max_successes) { FailingWriteFuncState state = {0, max_successes}; - SerdByteSink* out = - serd_byte_sink_new_function(failing_write_func, NULL, &state, 1); + SerdOutputStream out = + serd_open_output_stream(failing_write_func, NULL, &state); - SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0, env, out); + SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0, env, &out, 1); const SerdSink* const sink = serd_writer_sink(writer); SerdCursor* const all = serd_model_begin(model); @@ -1285,7 +1293,7 @@ test_write_error_in_list_subject(SerdWorld* world, const unsigned n_quads) assert(st == SERD_ERR_BAD_WRITE); serd_writer_free(writer); - serd_byte_sink_free(out); + serd_close_output(&out); } serd_env_free(env); @@ -1328,10 +1336,10 @@ test_write_error_in_list_object(SerdWorld* world, const unsigned n_quads) for (size_t max_successes = 0; max_successes < 21; ++max_successes) { FailingWriteFuncState state = {0, max_successes}; - SerdByteSink* out = - serd_byte_sink_new_function(failing_write_func, NULL, &state, 1); + SerdOutputStream out = + serd_open_output_stream(failing_write_func, NULL, &state); - SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0, env, out); + SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0, env, &out, 1); const SerdSink* const sink = serd_writer_sink(writer); SerdCursor* const all = serd_model_begin(model); @@ -1341,7 +1349,7 @@ test_write_error_in_list_object(SerdWorld* world, const unsigned n_quads) assert(st == SERD_ERR_BAD_WRITE); serd_writer_free(writer); - serd_byte_sink_free(out); + serd_close_output(&out); } serd_env_free(env); diff --git a/test/test_reader_writer.c b/test/test_reader_writer.c index b8afd649..bd83b082 100644 --- a/test/test_reader_writer.c +++ b/test/test_reader_writer.c @@ -43,11 +43,10 @@ test_writer(const char* const path) SerdWorld* world = serd_world_new(); SerdNodes* nodes = serd_world_nodes(world); - SerdByteSink* byte_sink = serd_byte_sink_new_function( - (SerdWriteFunc)fwrite, (SerdStreamCloseFunc)fclose, fd, 1); + SerdOutputStream output = serd_open_output_file(path); SerdWriter* writer = - serd_writer_new(world, SERD_TURTLE, SERD_WRITE_LAX, env, byte_sink); + serd_writer_new(world, SERD_TURTLE, SERD_WRITE_LAX, env, &output, 1); assert(writer); @@ -106,13 +105,13 @@ test_writer(const char* const path) assert(!serd_sink_write(iface, 0, s, p, hello, 0)); serd_writer_free(writer); - serd_byte_sink_free(byte_sink); + serd_close_output(&output); // Test buffer sink SerdBuffer buffer = {NULL, 0}; - byte_sink = serd_byte_sink_new_buffer(&buffer); - writer = serd_writer_new(world, SERD_TURTLE, 0, env, byte_sink); + output = serd_open_output_buffer(&buffer); + writer = serd_writer_new(world, SERD_TURTLE, 0, env, &output, 1); const SerdNode* const base = serd_nodes_uri(nodes, SERD_STRING("http://example.org/base")); @@ -120,9 +119,10 @@ test_writer(const char* const path) serd_writer_set_base_uri(writer, base); serd_writer_free(writer); - serd_byte_sink_free(byte_sink); + serd_close_output(&output); char* out = (char*)buffer.buf; + assert(out); assert(!strcmp(out, "@base .\n")); serd_free(out); diff --git a/test/test_terse_write.c b/test/test_terse_write.c index aeb264ea..d9ce4d1b 100644 --- a/test/test_terse_write.c +++ b/test/test_terse_write.c @@ -64,9 +64,9 @@ test(void) serd_env_set_prefix(env, SERD_STRING("rdf"), SERD_STRING(NS_RDF)); - SerdByteSink* const byte_sink = serd_byte_sink_new_buffer(&buffer); - SerdWriter* const writer = - serd_writer_new(world, SERD_TURTLE, 0, env, byte_sink); + SerdOutputStream output = serd_open_output_buffer(&buffer); + SerdWriter* const writer = + serd_writer_new(world, SERD_TURTLE, 0, env, &output, 1); const SerdSink* const sink = serd_writer_sink(writer); @@ -99,7 +99,7 @@ test(void) check_output(writer, &buffer, "[]\n\trdf:value ( \"s1\" \"s2\" ) .\n"); serd_writer_free(writer); - serd_byte_sink_free(byte_sink); + serd_close_output(&output); serd_nodes_free(nodes); serd_env_free(env); serd_world_free(world); diff --git a/test/test_writer.c b/test/test_writer.c index 83d4087c..34eafbb2 100644 --- a/test/test_writer.c +++ b/test/test_writer.c @@ -25,30 +25,44 @@ #include #include +static void +test_writer_new(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); + + assert(!serd_writer_new(world, SERD_TURTLE, 0u, env, &output, 0)); + + serd_world_free(world); + serd_env_free(env); +} + static void test_write_bad_event(void) { - SerdWorld* world = serd_world_new(); - SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); - SerdBuffer buffer = {NULL, 0}; - SerdByteSink* byte_sink = serd_byte_sink_new_buffer(&buffer); + 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, byte_sink); + SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0u, env, &output, 1); assert(writer); const SerdEvent event = {(SerdEventType)42}; assert(serd_sink_write_event(serd_writer_sink(writer), &event) == SERD_ERR_BAD_ARG); - assert(!serd_byte_sink_close(byte_sink)); + assert(!serd_close_output(&output)); char* const out = (char*)buffer.buf; + assert(out); assert(!strcmp(out, "")); serd_free(out); serd_writer_free(writer); - serd_byte_sink_free(byte_sink); serd_env_free(env); serd_world_free(world); } @@ -56,13 +70,13 @@ test_write_bad_event(void) static void test_write_long_literal(void) { - SerdWorld* world = serd_world_new(); - SerdNodes* nodes = serd_world_nodes(world); - SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); - SerdBuffer buffer = {NULL, 0}; - SerdByteSink* byte_sink = serd_byte_sink_new_buffer(&buffer); + SerdWorld* world = serd_world_new(); + SerdNodes* nodes = serd_world_nodes(world); + 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, byte_sink); + SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0u, env, &output, 1); assert(writer); const SerdNode* s = @@ -81,7 +95,7 @@ test_write_long_literal(void) assert(!serd_sink_write(serd_writer_sink(writer), 0, s, p, o, NULL)); serd_writer_free(writer); - serd_byte_sink_free(byte_sink); + serd_close_output(&output); serd_env_free(env); serd_buffer_close(&buffer); @@ -112,13 +126,12 @@ null_sink(const void* const buf, static void test_writer_stack_overflow(void) { - SerdWorld* world = serd_world_new(); - SerdNodes* nodes = serd_world_nodes(world); - SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); - SerdByteSink* byte_sink = - serd_byte_sink_new_function(null_sink, NULL, NULL, 1u); + SerdWorld* world = serd_world_new(); + SerdNodes* nodes = serd_world_nodes(world); + SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); + SerdOutputStream output = serd_open_output_stream(null_sink, NULL, NULL); - SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0u, env, byte_sink); + SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0u, env, &output, 1); const SerdSink* sink = serd_writer_sink(writer); @@ -153,7 +166,7 @@ test_writer_stack_overflow(void) assert(st == SERD_ERR_OVERFLOW); serd_writer_free(writer); - serd_byte_sink_free(byte_sink); + serd_close_output(&output); serd_env_free(env); serd_world_free(world); } @@ -161,18 +174,16 @@ test_writer_stack_overflow(void) static void test_strict_write(void) { - SerdWorld* world = serd_world_new(); - SerdNodes* nodes = serd_world_nodes(world); - const char* path = "serd_strict_write_test.ttl"; - FILE* fd = fopen(path, "wb"); - assert(fd); + static const char* path = "serd_strict_write_test.ttl"; - SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); + SerdWorld* world = serd_world_new(); + SerdNodes* nodes = serd_world_nodes(world); + SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); - SerdByteSink* byte_sink = serd_byte_sink_new_function( - (SerdWriteFunc)fwrite, (SerdStreamCloseFunc)fclose, fd, 1); + SerdOutputStream output = serd_open_output_file(path); + assert(output.stream); - SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0, env, byte_sink); + SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0, env, &output, 1); assert(writer); const SerdSink* sink = serd_writer_sink(writer); @@ -192,7 +203,7 @@ test_strict_write(void) assert(serd_sink_write(sink, 0, s, p, bad_uri, 0) == SERD_ERR_BAD_TEXT); serd_writer_free(writer); - serd_byte_sink_free(byte_sink); + serd_close_output(&output); serd_env_free(env); serd_world_free(world); } @@ -233,21 +244,20 @@ test_write_error(void) // Test with setting errno - SerdByteSink* byte_sink = - serd_byte_sink_new_function(faulty_sink, NULL, NULL, 1); + SerdOutputStream output = serd_open_output_stream(faulty_sink, NULL, NULL); - SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0u, env, byte_sink); + SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0u, env, &output, 1); assert(writer); SerdStatus st = serd_sink_write(serd_writer_sink(writer), 0u, s, p, o, NULL); assert(st == SERD_ERR_BAD_WRITE); serd_writer_free(writer); - serd_byte_sink_free(byte_sink); + serd_close_output(&output); // Test without setting errno - byte_sink = serd_byte_sink_new_function(faulty_sink, NULL, world, 1); - writer = serd_writer_new(world, SERD_TURTLE, 0u, env, byte_sink); + output = serd_open_output_stream(faulty_sink, NULL, world); + writer = serd_writer_new(world, SERD_TURTLE, 0u, env, &output, 1); assert(writer); @@ -255,7 +265,7 @@ test_write_error(void) SERD_ERR_BAD_WRITE); serd_writer_free(writer); - serd_byte_sink_free(byte_sink); + serd_close_output(&output); serd_env_free(env); serd_world_free(world); @@ -277,24 +287,25 @@ test_write_empty_syntax(void) const SerdNode* o = serd_nodes_uri(nodes, SERD_STRING("http://example.org/o")); - SerdBuffer buffer = {NULL, 0}; - SerdByteSink* byte_sink = serd_byte_sink_new_buffer(&buffer); + SerdBuffer buffer = {NULL, 0}; + SerdOutputStream output = serd_open_output_buffer(&buffer); SerdWriter* writer = - serd_writer_new(world, SERD_SYNTAX_EMPTY, 0u, env, byte_sink); + serd_writer_new(world, SERD_SYNTAX_EMPTY, 0u, env, &output, 1); assert(writer); assert(!serd_sink_write(serd_writer_sink(writer), 0u, s, p, o, NULL)); - assert(!serd_byte_sink_close(byte_sink)); + assert(!serd_close_output(&output)); char* const out = (char*)buffer.buf; + assert(out); assert(strlen(out) == 0); serd_free(out); serd_writer_free(writer); - serd_byte_sink_free(byte_sink); + serd_close_output(&output); serd_env_free(env); serd_world_free(world); } @@ -314,11 +325,11 @@ test_write_bad_uri(void) const SerdNode* rel = serd_nodes_uri(nodes, SERD_STRING("rel")); - SerdBuffer buffer = {NULL, 0}; - SerdByteSink* byte_sink = serd_byte_sink_new_buffer(&buffer); + SerdBuffer buffer = {NULL, 0}; + SerdOutputStream output = serd_open_output_buffer(&buffer); SerdWriter* writer = - serd_writer_new(world, SERD_NTRIPLES, 0u, env, byte_sink); + serd_writer_new(world, SERD_NTRIPLES, 0u, env, &output, 1); assert(writer); @@ -328,10 +339,10 @@ test_write_bad_uri(void) assert(st); assert(st == SERD_ERR_BAD_ARG); - serd_byte_sink_close(byte_sink); + serd_close_output(&output); serd_free(buffer.buf); serd_writer_free(writer); - serd_byte_sink_free(byte_sink); + serd_close_output(&output); serd_env_free(env); serd_world_free(world); } @@ -339,13 +350,13 @@ test_write_bad_uri(void) static void check_pname_escape(const char* const lname, const char* const expected) { - SerdWorld* world = serd_world_new(); - SerdNodes* nodes = serd_world_nodes(world); - SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); - SerdBuffer buffer = {NULL, 0}; - SerdByteSink* byte_sink = serd_byte_sink_new_buffer(&buffer); + SerdWorld* world = serd_world_new(); + SerdNodes* nodes = serd_world_nodes(world); + 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, byte_sink); + SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0u, env, &output, 1); assert(writer); static const char* const prefix = "http://example.org/"; @@ -368,7 +379,7 @@ check_pname_escape(const char* const lname, const char* const expected) assert(!serd_sink_write(serd_writer_sink(writer), 0, s, p, node, NULL)); serd_writer_free(writer); - serd_byte_sink_free(byte_sink); + serd_close_output(&output); serd_env_free(env); serd_buffer_close(&buffer); @@ -415,6 +426,7 @@ test_write_pname_escapes(void) int main(void) { + test_writer_new(); test_write_bad_event(); test_write_long_literal(); test_writer_stack_overflow(); -- cgit v1.2.1