diff options
author | David Robillard <d@drobilla.net> | 2018-04-29 15:24:05 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2020-10-27 13:13:58 +0100 |
commit | 3bdf4986884e26b40b0c9d010634a0c572c84122 (patch) | |
tree | 666235b035bf0d637d15c6461393508f90660801 | |
parent | 79bd5c789631ea51071564813046e34b304e1bc7 (diff) | |
download | serd-3bdf4986884e26b40b0c9d010634a0c572c84122.tar.gz serd-3bdf4986884e26b40b0c9d010634a0c572c84122.tar.bz2 serd-3bdf4986884e26b40b0c9d010634a0c572c84122.zip |
Add SerdWorld for shared library state
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | serd/serd.h | 71 | ||||
-rw-r--r-- | src/reader.c | 14 | ||||
-rw-r--r-- | src/reader.h | 1 | ||||
-rw-r--r-- | src/serd_internal.h | 18 | ||||
-rw-r--r-- | src/serdi.c | 14 | ||||
-rw-r--r-- | src/world.c | 40 | ||||
-rw-r--r-- | src/world.h | 27 | ||||
-rw-r--r-- | src/writer.c | 18 | ||||
-rw-r--r-- | tests/free_null_test.c | 1 | ||||
-rw-r--r-- | tests/read_chunk_test.c | 6 | ||||
-rw-r--r-- | tests/serd_test.c | 26 | ||||
-rw-r--r-- | wscript | 2 |
13 files changed, 172 insertions, 67 deletions
@@ -1,6 +1,7 @@ serd (1.0.1) unstable; * Add SerdBuffer for mutable buffers to keep SerdChunk const-correct + * Add SerdWorld for shared library state * Bring read/write interface closer to C standard * Make nodes opaque * Make serd_strtod API const-correct diff --git a/serd/serd.h b/serd/serd.h index 0cc64090..2ca6a19c 100644 --- a/serd/serd.h +++ b/serd/serd.h @@ -58,6 +58,13 @@ extern "C" { */ /** + World. + + The World represents all library state shared between various objects. +*/ +typedef struct SerdWorldImpl SerdWorld; + +/** Environment. Represents the state required to resolve a CURIE or relative URI, e.g. the @@ -716,6 +723,41 @@ typedef struct SerdSink { /** @} + @name World + @{ +*/ + +/** + Create a new Serd World. + + It is safe to use multiple worlds in one process, though no objects can be + shared between worlds. +*/ +SERD_API +SerdWorld* +serd_world_new(void); + +/** + Free `world`. +*/ +SERD_API +void +serd_world_free(SerdWorld* world); + +/** + Set a function to be called when errors occur. + + The `error_sink` will be called with `handle` as its first argument. If + no error function is set, errors are printed to stderr. +*/ +SERD_API +void +serd_world_set_error_sink(SerdWorld* world, + SerdErrorSink error_sink, + void* handle); + +/** + @} @name Environment @{ */ @@ -820,7 +862,7 @@ serd_env_foreach(const SerdEnv* env, */ SERD_API SerdReader* -serd_reader_new(SerdSyntax syntax, const SerdSink* sink); +serd_reader_new(SerdWorld* world, SerdSyntax syntax, const SerdSink* sink); /** Enable or disable strict parsing. @@ -834,18 +876,6 @@ void serd_reader_set_strict(SerdReader* reader, bool strict); /** - Set a function to be called when errors occur during reading. - - The `error_sink` will be called with `handle` as its first argument. If - no error function is set, errors are printed to stderr in GCC style. -*/ -SERD_API -void -serd_reader_set_error_sink(SerdReader* reader, - SerdErrorSink error_sink, - void* error_handle); - -/** Set a prefix to be added to all blank node identifiers. This is useful when multiple files are to be parsed into the same output @@ -956,7 +986,8 @@ serd_reader_free(SerdReader* reader); */ SERD_API SerdWriter* -serd_writer_new(SerdSyntax syntax, +serd_writer_new(SerdWorld* world, + SerdSyntax syntax, SerdStyle style, SerdEnv* env, const SerdURI* base_uri, @@ -1007,18 +1038,6 @@ char* serd_buffer_sink_finish(SerdBuffer* stream); /** - Set a function to be called when errors occur during writing. - - The `error_sink` will be called with `handle` as its first argument. If - no error function is set, errors are printed to stderr. -*/ -SERD_API -void -serd_writer_set_error_sink(SerdWriter* writer, - SerdErrorSink error_sink, - void* error_handle); - -/** Set a prefix to be removed from matching blank node identifiers. */ SERD_API diff --git a/src/reader.c b/src/reader.c index 0f097a02..eafc4606 100644 --- a/src/reader.c +++ b/src/reader.c @@ -34,7 +34,7 @@ r_err(SerdReader* reader, SerdStatus st, const char* fmt, ...) va_start(args, fmt); const Cursor* const cur = &reader->source.cur; const SerdError e = { st, cur->filename, cur->line, cur->col, fmt, &args }; - serd_error(reader->error_sink, reader->error_handle, &e); + serd_error(reader->world, &e); va_end(args); return st; } @@ -158,10 +158,11 @@ serd_reader_read_document(SerdReader* reader) } SerdReader* -serd_reader_new(SerdSyntax syntax, const SerdSink* sink) +serd_reader_new(SerdWorld* world, SerdSyntax syntax, const SerdSink* sink) { SerdReader* me = (SerdReader*)calloc(1, sizeof(SerdReader)); + me->world = world; me->sink = sink; me->default_graph = NULL; me->stack = serd_stack_new(SERD_PAGE_SIZE); @@ -183,15 +184,6 @@ serd_reader_set_strict(SerdReader* reader, bool strict) } void -serd_reader_set_error_sink(SerdReader* reader, - SerdErrorSink error_sink, - void* error_handle) -{ - reader->error_sink = error_sink; - reader->error_handle = error_handle; -} - -void serd_reader_free(SerdReader* reader) { if (!reader) { diff --git a/src/reader.h b/src/reader.h index 10e72384..d3d27f39 100644 --- a/src/reader.h +++ b/src/reader.h @@ -57,6 +57,7 @@ typedef struct { } ReadContext; struct SerdReaderImpl { + SerdWorld* world; const SerdSink* sink; SerdErrorSink error_sink; void* error_handle; diff --git a/src/serd_internal.h b/src/serd_internal.h index 03d4edbd..26846312 100644 --- a/src/serd_internal.h +++ b/src/serd_internal.h @@ -17,8 +17,14 @@ #ifndef SERD_INTERNAL_H #define SERD_INTERNAL_H +#include "world.h" + #include "serd/serd.h" +#if defined(HAVE_POSIX_FADVISE) && defined(HAVE_FILENO) +# include <fcntl.h> +#endif + #include <assert.h> #include <ctype.h> #include <errno.h> @@ -38,12 +44,16 @@ /* Error reporting */ static inline void -serd_error(SerdErrorSink error_sink, void* handle, const SerdError* e) +serd_error(const SerdWorld* world, const SerdError* e) { - if (error_sink) { - error_sink(handle, e); + if (world->error_sink) { + world->error_sink(world->error_handle, e); } else { - fprintf(stderr, "error: %s:%u:%u: ", e->filename, e->line, e->col); + if (e->filename) { + fprintf(stderr, "error: %s:%u:%u: ", e->filename, e->line, e->col); + } else { + fprintf(stderr, "error: "); + } vfprintf(stderr, e->fmt, *e->args); } } diff --git a/src/serdi.c b/src/serdi.c index 151465d9..ead49126 100644 --- a/src/serdi.c +++ b/src/serdi.c @@ -289,8 +289,9 @@ main(int argc, char** argv) base = serd_node_new_file_uri(input, NULL, &base_uri, true); } - FILE* out_fd = stdout; - SerdEnv* env = serd_env_new(base); + FILE* out_fd = stdout; + SerdWorld* world = serd_world_new(); + SerdEnv* env = serd_env_new(base); int output_style = 0; if (output_syntax == SERD_NTRIPLES || ascii) { @@ -312,7 +313,8 @@ main(int argc, char** argv) output_style |= SERD_STYLE_BULK; } - SerdWriter* writer = serd_writer_new(output_syntax, + SerdWriter* writer = serd_writer_new(world, + output_syntax, (SerdStyle)output_style, env, &base_uri, @@ -320,12 +322,11 @@ main(int argc, char** argv) out_fd); SerdReader* reader = - serd_reader_new(input_syntax, serd_writer_get_sink(writer)); + serd_reader_new(world, input_syntax, serd_writer_get_sink(writer)); serd_reader_set_strict(reader, !lax); if (quiet) { - serd_reader_set_error_sink(reader, quiet_error_sink, NULL); - serd_writer_set_error_sink(writer, quiet_error_sink, NULL); + serd_world_set_error_sink(world, quiet_error_sink, NULL); } SerdNode* root = serd_node_new_string(SERD_URI, root_uri); @@ -358,6 +359,7 @@ main(int argc, char** argv) serd_writer_free(writer); serd_env_free(env); serd_node_free(base); + serd_world_free(world); free(input_path); if (from_file) { diff --git a/src/world.c b/src/world.c new file mode 100644 index 00000000..483a33af --- /dev/null +++ b/src/world.c @@ -0,0 +1,40 @@ +/* + Copyright 2011-2020 David Robillard <http://drobilla.net> + + 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. +*/ + +#include "world.h" + +#include <stdlib.h> + +SerdWorld* +serd_world_new(void) +{ + return (SerdWorld*)calloc(1, sizeof(SerdWorld)); +} + +void +serd_world_free(SerdWorld* world) +{ + free(world); +} + +void +serd_world_set_error_sink(SerdWorld* world, + SerdErrorSink error_sink, + void* handle) +{ + world->error_sink = error_sink; + world->error_handle = handle; +} diff --git a/src/world.h b/src/world.h new file mode 100644 index 00000000..87479eab --- /dev/null +++ b/src/world.h @@ -0,0 +1,27 @@ +/* + Copyright 2011-2020 David Robillard <http://drobilla.net> + + 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. +*/ + +#ifndef SERD_WORLD_H +#define SERD_WORLD_H + +#include "serd/serd.h" + +struct SerdWorldImpl { + SerdErrorSink error_sink; + void* error_handle; +}; + +#endif // SERD_WORLD_H diff --git a/src/writer.c b/src/writer.c index 4da374aa..588fb769 100644 --- a/src/writer.c +++ b/src/writer.c @@ -93,6 +93,7 @@ static const SepRule rules[] = { }; struct SerdWriterImpl { + SerdWorld* world; SerdSink iface; SerdSyntax syntax; SerdStyle style; @@ -147,8 +148,8 @@ w_err(SerdWriter* writer, SerdStatus st, const char* fmt, ...) va_list args; va_start(args, fmt); - const SerdError e = { st, "", 0, 0, fmt, &args }; - serd_error(writer->error_sink, writer->error_handle, &e); + const SerdError e = { st, NULL, 0, 0, fmt, &args }; + serd_error(writer->world, &e); va_end(args); } @@ -877,7 +878,8 @@ serd_writer_finish(SerdWriter* writer) } SerdWriter* -serd_writer_new(SerdSyntax syntax, +serd_writer_new(SerdWorld* world, + SerdSyntax syntax, SerdStyle style, SerdEnv* env, const SerdURI* base_uri, @@ -886,6 +888,7 @@ serd_writer_new(SerdSyntax syntax, { const WriteContext context = WRITE_CONTEXT_NULL; SerdWriter* writer = (SerdWriter*)calloc(1, sizeof(SerdWriter)); + writer->world = world; writer->syntax = syntax; writer->style = style; writer->env = env; @@ -909,15 +912,6 @@ serd_writer_new(SerdSyntax syntax, } void -serd_writer_set_error_sink(SerdWriter* writer, - SerdErrorSink error_sink, - void* error_handle) -{ - writer->error_sink = error_sink; - writer->error_handle = error_handle; -} - -void serd_writer_chop_blank_prefix(SerdWriter* writer, const char* prefix) { diff --git a/tests/free_null_test.c b/tests/free_null_test.c index 121a66cd..08f2b513 100644 --- a/tests/free_null_test.c +++ b/tests/free_null_test.c @@ -25,6 +25,7 @@ main(void) { serd_free(NULL); serd_node_free(NULL); + serd_world_free(NULL); serd_env_free(NULL); serd_reader_free(NULL); serd_writer_free(NULL); diff --git a/tests/read_chunk_test.c b/tests/read_chunk_test.c index 3cc32bd9..decfe829 100644 --- a/tests/read_chunk_test.c +++ b/tests/read_chunk_test.c @@ -79,9 +79,10 @@ on_end(void* handle, const SerdNode* node) int main(void) { - const SerdSink sink = {NULL, on_base, on_prefix, on_statement, on_end}; + SerdWorld* world = serd_world_new(); + const SerdSink sink = {NULL, on_base, on_prefix, on_statement, on_end}; - SerdReader* reader = serd_reader_new(SERD_TURTLE, &sink); + SerdReader* reader = serd_reader_new(world, SERD_TURTLE, &sink); assert(reader); assert(!serd_reader_start_string(reader, @@ -106,5 +107,6 @@ main(void) assert(serd_reader_read_chunk(reader) == SERD_FAILURE); serd_reader_free(reader); + serd_world_free(world); return 0; } diff --git a/tests/serd_test.c b/tests/serd_test.c index acfd1a7b..2171710b 100644 --- a/tests/serd_test.c +++ b/tests/serd_test.c @@ -126,11 +126,12 @@ test_file_uri(const char* hostname, static void test_read_chunks(void) { + SerdWorld* world = serd_world_new(); ReaderTest* const rt = (ReaderTest*)calloc(1, sizeof(ReaderTest)); FILE* const f = tmpfile(); static const char null = 0; SerdSink sink = {rt, NULL, NULL, test_sink, NULL}; - SerdReader* reader = serd_reader_new(SERD_TURTLE, &sink); + SerdReader* reader = serd_reader_new(world, SERD_TURTLE, &sink); assert(reader); assert(f); @@ -184,14 +185,16 @@ test_read_chunks(void) serd_reader_free(reader); fclose(f); free(rt); + serd_world_free(world); } static void test_read_string(void) { + SerdWorld* world = serd_world_new(); ReaderTest* rt = (ReaderTest*)calloc(1, sizeof(ReaderTest)); SerdSink sink = {rt, NULL, NULL, test_sink, NULL}; - SerdReader* reader = serd_reader_new(SERD_TURTLE, &sink); + SerdReader* reader = serd_reader_new(world, SERD_TURTLE, &sink); assert(reader); // Test reading a string that ends exactly at the end of input (no newline) @@ -204,6 +207,7 @@ test_read_string(void) assert(rt->n_statements == 1); serd_reader_free(reader); + serd_world_free(world); } static void @@ -501,8 +505,15 @@ test_writer(const char* const path) SerdEnv* env = serd_env_new(NULL); assert(fd); - SerdWriter* writer = serd_writer_new( - SERD_TURTLE, (SerdStyle)0, env, NULL, (SerdWriteFunc)fwrite, fd); + SerdWorld* world = serd_world_new(); + + SerdWriter* writer = serd_writer_new(world, + SERD_TURTLE, + (SerdStyle)0, + env, + NULL, + (SerdWriteFunc)fwrite, + fd); assert(writer); serd_writer_chop_blank_prefix(writer, "tmp"); @@ -578,7 +589,7 @@ test_writer(const char* const path) // Test buffer sink SerdBuffer buffer = { NULL, 0 }; writer = serd_writer_new( - SERD_TURTLE, (SerdStyle)0, env, NULL, serd_buffer_sink, &buffer); + world, SERD_TURTLE, (SerdStyle)0, env, NULL, serd_buffer_sink, &buffer); o = serd_node_new_string(SERD_URI, "http://example.org/base"); assert(!serd_writer_set_base_uri(writer, o)); @@ -591,15 +602,17 @@ test_writer(const char* const path) serd_free(out); serd_env_free(env); + serd_world_free(world); fclose(fd); } static void test_reader(const char* path) { + SerdWorld* world = serd_world_new(); ReaderTest* rt = (ReaderTest*)calloc(1, sizeof(ReaderTest)); SerdSink sink = { rt, NULL, NULL, test_sink, NULL }; - SerdReader* reader = serd_reader_new(SERD_TURTLE, &sink); + SerdReader* reader = serd_reader_new(world, SERD_TURTLE, &sink); assert(reader); SerdNode* g = serd_node_new_string(SERD_URI, "http://example.org/"); @@ -661,6 +674,7 @@ test_reader(const char* path) serd_reader_free(reader); free(rt); + serd_world_free(world); } int @@ -72,6 +72,7 @@ def configure(conf): '-Wno-padded', '-Wno-sign-conversion', '-Wno-suggest-attribute=const', + '-Wno-suggest-attribute=malloc', '-Wno-suggest-attribute=pure', ], 'msvc': [ @@ -151,6 +152,7 @@ lib_source = ['src/base64.c', 'src/string.c', 'src/system.c', 'src/uri.c', + 'src/world.c', 'src/writer.c'] |