aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-04-29 15:24:05 +0200
committerDavid Robillard <d@drobilla.net>2019-12-19 20:52:30 -0500
commit5e2a5940e17f498f4cbec37ee7380a42f511c82a (patch)
tree6f33d275c19bbbc44e8f27d775216fa38262634f
parent9577022620cab6005c7f46348c617898f068e479 (diff)
downloadserd-5e2a5940e17f498f4cbec37ee7380a42f511c82a.tar.gz
serd-5e2a5940e17f498f4cbec37ee7380a42f511c82a.tar.bz2
serd-5e2a5940e17f498f4cbec37ee7380a42f511c82a.zip
Add SerdWorld for shared library state
-rw-r--r--NEWS1
-rw-r--r--serd/serd.h71
-rw-r--r--src/reader.c14
-rw-r--r--src/reader.h3
-rw-r--r--src/serd_internal.h8
-rw-r--r--src/serdi.c14
-rw-r--r--src/world.c40
-rw-r--r--src/world.h27
-rw-r--r--src/writer.c16
-rw-r--r--tests/serd_test.c22
-rw-r--r--wscript1
11 files changed, 154 insertions, 63 deletions
diff --git a/NEWS b/NEWS
index f237c974..22b2cca5 100644
--- a/NEWS
+++ b/NEWS
@@ -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 51248442..7aa0ebdd 100644
--- a/serd/serd.h
+++ b/serd/serd.h
@@ -55,6 +55,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
@{
*/
@@ -821,7 +863,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.
@@ -835,18 +877,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
@@ -957,7 +987,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,
@@ -1008,18 +1039,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 e9bc68fa..138ef336 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -36,7 +36,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 0;
}
@@ -156,10 +156,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);
@@ -181,15 +182,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)
{
pop_node(reader, reader->rdf_nil);
diff --git a/src/reader.h b/src/reader.h
index 405af546..f8116949 100644
--- a/src/reader.h
+++ b/src/reader.h
@@ -52,7 +52,8 @@ typedef struct {
} ReadContext;
struct SerdReaderImpl {
- const SerdSink* sink;
+ SerdWorld* world;
+ const SerdSink* sink;
SerdErrorSink error_sink;
void* error_handle;
Ref rdf_first;
diff --git a/src/serd_internal.h b/src/serd_internal.h
index fbf493e9..172343b8 100644
--- a/src/serd_internal.h
+++ b/src/serd_internal.h
@@ -27,6 +27,8 @@
#include "serd/serd.h"
#include "serd_config.h"
+#include "world.h"
+
#if defined(HAVE_POSIX_FADVISE) && defined(HAVE_FILENO)
# include <fcntl.h>
#endif
@@ -68,10 +70,10 @@ serd_bufalloc(size_t size)
}
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);
vfprintf(stderr, e->fmt, *e->args);
diff --git a/src/serdi.c b/src/serdi.c
index 6656ccd2..eda73c2c 100644
--- a/src/serdi.c
+++ b/src/serdi.c
@@ -264,8 +264,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) {
@@ -287,7 +288,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,
@@ -295,12 +297,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);
@@ -331,6 +332,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..07439137
--- /dev/null
+++ b/src/world.c
@@ -0,0 +1,40 @@
+/*
+ Copyright 2011-2018 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 "serd_internal.h"
+
+#include "world.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..88241b0e
--- /dev/null
+++ b/src/world.h
@@ -0,0 +1,27 @@
+/*
+ Copyright 2011-2018 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_internal.h"
+
+struct SerdWorldImpl {
+ SerdErrorSink error_sink;
+ void* error_handle;
+};
+
+#endif // SERD_WORLD_H
diff --git a/src/writer.c b/src/writer.c
index 5c457566..4c9f625d 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -89,6 +89,7 @@ static const SepRule rules[] = {
};
struct SerdWriterImpl {
+ SerdWorld* world;
SerdSink iface;
SerdSyntax syntax;
SerdStyle style;
@@ -144,7 +145,7 @@ w_err(SerdWriter* writer, SerdStatus st, const char* fmt, ...)
va_list args;
va_start(args, fmt);
const SerdError e = { st, NULL, 0, 0, fmt, &args };
- serd_error(writer->error_sink, writer->error_handle, &e);
+ serd_error(writer->world, &e);
va_end(args);
}
@@ -870,7 +871,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,
@@ -879,6 +881,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;
@@ -902,15 +905,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/serd_test.c b/tests/serd_test.c
index 5998588c..ba8ca2ce 100644
--- a/tests/serd_test.c
+++ b/tests/serd_test.c
@@ -108,11 +108,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);
@@ -171,6 +172,7 @@ test_read_chunks(void)
serd_reader_free(reader);
fclose(f);
free(rt);
+ serd_world_free(world);
}
static void
@@ -530,8 +532,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");
@@ -609,7 +618,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));
@@ -621,15 +630,17 @@ test_writer(const char* const path)
assert(!strcmp(out, "@base <http://example.org/base> .\n"));
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/");
@@ -652,6 +663,7 @@ test_reader(const char* path)
serd_reader_free(reader);
free(rt);
+ serd_world_free(world);
}
int
diff --git a/wscript b/wscript
index 449d5852..83901b62 100644
--- a/wscript
+++ b/wscript
@@ -87,6 +87,7 @@ lib_source = ['src/byte_source.c',
'src/reader.c',
'src/string.c',
'src/uri.c',
+ 'src/world.c',
'src/writer.c']
def build(bld):