aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-05-05 16:12:38 +0200
committerDavid Robillard <d@drobilla.net>2019-12-20 10:26:55 -0500
commitc55d1fd13c2f49c8ef1b4e2060f846ecd4eabbc1 (patch)
treed5877facdaad01f3dd0998a21c5f4631cd9d0fc2
parent48003ea5959c56a3204a2222a147d2bf1ecd96c9 (diff)
downloadserd-c55d1fd13c2f49c8ef1b4e2060f846ecd4eabbc1.tar.gz
serd-c55d1fd13c2f49c8ef1b4e2060f846ecd4eabbc1.tar.bz2
serd-c55d1fd13c2f49c8ef1b4e2060f846ecd4eabbc1.zip
Add support for reading multiple files at once
-rw-r--r--doc/serdi.14
-rw-r--r--src/serdi.c123
-rw-r--r--tests/multifile/input1.ttl2
-rw-r--r--tests/multifile/input2.trig7
-rw-r--r--tests/multifile/output.nq3
-rw-r--r--wscript9
6 files changed, 112 insertions, 36 deletions
diff --git a/doc/serdi.1 b/doc/serdi.1
index 3e1d2ebd..2bef4922 100644
--- a/doc/serdi.1
+++ b/doc/serdi.1
@@ -1,10 +1,10 @@
-.TH SERDI 1 "06 Jan 2019"
+.TH SERDI 1 "05 May 2019"
.SH NAME
.B serdi \- Read and write RDF syntax
.SH SYNOPSIS
-serdi [\fIOPTION\fR]... \fIINPUT\fR
+serdi [\fIOPTION\fR]... \fIINPUT\fR...
.SH OPTIONS
diff --git a/src/serdi.c b/src/serdi.c
index 81b4dc1f..763f495e 100644
--- a/src/serdi.c
+++ b/src/serdi.c
@@ -89,6 +89,45 @@ quiet_error_func(void* handle, const SerdLogEntry* entry)
return SERD_SUCCESS;
}
+static SerdStatus
+read_file(SerdWorld* const world,
+ SerdSyntax syntax,
+ const SerdReaderFlags flags,
+ const SerdSink* const sink,
+ const size_t stack_size,
+ const char* filename,
+ const char* add_prefix,
+ bool bulk_read)
+{
+ syntax = syntax ? syntax : serd_guess_syntax(filename);
+ syntax = syntax ? syntax : SERD_TRIG;
+
+ SerdStatus st = SERD_SUCCESS;
+ SerdReader* reader =
+ serd_reader_new(world, syntax, flags, sink, stack_size);
+
+ serd_reader_add_blank_prefix(reader, add_prefix);
+
+ if (!strcmp(filename, "-")) {
+ SerdNode* name = serd_new_string("stdin");
+ st = serd_reader_start_stream(reader,
+ serd_file_read_byte,
+ (SerdStreamErrorFunc)ferror,
+ stdin,
+ name,
+ 1);
+ serd_node_free(name);
+ } else {
+ st = serd_reader_start_file(reader, filename, bulk_read);
+ }
+
+ st = st ? st : serd_reader_read_document(reader);
+
+ serd_reader_free(reader);
+
+ return st;
+}
+
int
main(int argc, char** argv)
{
@@ -101,7 +140,6 @@ main(int argc, char** argv)
SerdSyntax output_syntax = SERD_SYNTAX_EMPTY;
SerdReaderFlags reader_flags = 0;
SerdWriterFlags writer_flags = 0;
- bool from_stdin = false;
bool bulk_read = true;
bool bulk_write = false;
bool no_inline = false;
@@ -110,13 +148,12 @@ main(int argc, char** argv)
bool quiet = false;
size_t stack_size = 4194304;
const char* input_string = NULL;
- const char* add_prefix = NULL;
+ const char* add_prefix = "";
const char* chop_prefix = NULL;
const char* root_uri = NULL;
int a = 1;
for (; a < argc && argv[a][0] == '-'; ++a) {
if (argv[a][1] == '\0') {
- from_stdin = true;
break;
} else if (argv[a][1] == 'I') {
if (++a == argc) {
@@ -206,21 +243,18 @@ main(int argc, char** argv)
_setmode(_fileno(stdout), _O_BINARY);
#endif
- const char* input = argv[a++];
-
- if (!input_syntax && !input || !(input_syntax = serd_guess_syntax(input))) {
- input_syntax = SERD_TRIG;
+ bool input_has_graphs = serd_syntax_has_graphs(input_syntax);
+ for (int i = a; i < argc; ++i) {
+ if (serd_syntax_has_graphs(serd_guess_syntax(argv[i]))) {
+ input_has_graphs = true;
+ break;
+ }
}
- const bool input_has_graphs = serd_syntax_has_graphs(input_syntax);
if (!output_syntax && !osyntax_set) {
output_syntax = input_has_graphs ? SERD_NQUADS : SERD_NTRIPLES;
}
- if (!base && input) {
- base = serd_new_file_uri(input, NULL);
- }
-
FILE* out_fd = stdout;
SerdWorld* world = serd_world_new();
SerdEnv* env = serd_env_new(base);
@@ -238,7 +272,6 @@ main(int argc, char** argv)
(SerdWriteFunc)serd_byte_sink_write,
byte_sink);
- SerdReader* reader = NULL;
SerdModel* model = NULL;
SerdInserter* inserter = NULL;
const SerdSink* sink = NULL;
@@ -253,9 +286,6 @@ main(int argc, char** argv)
sink = serd_writer_get_sink(writer);
}
- reader = serd_reader_new(
- world, input_syntax, reader_flags, sink, stack_size);
-
if (quiet) {
serd_world_set_log_func(world, quiet_error_func, NULL);
}
@@ -263,31 +293,59 @@ main(int argc, char** argv)
SerdNode* root = serd_new_uri(root_uri);
serd_writer_set_root_uri(writer, root);
serd_writer_chop_blank_prefix(writer, chop_prefix);
- serd_reader_add_blank_prefix(reader, add_prefix);
serd_node_free(root);
SerdStatus st = SERD_SUCCESS;
SerdNode* input_name = NULL;
if (input_string) {
- input_name = serd_new_string("string");
- st = serd_reader_start_string(reader, input_string, input_name);
- } else if (from_stdin) {
- input_name = serd_new_string("stdin");
- st = serd_reader_start_stream(reader,
- serd_file_read_byte,
- (SerdStreamErrorFunc)ferror,
- stdin,
- input_name,
- 1);
- } else {
- st = serd_reader_start_file(reader, input, bulk_read);
+ SerdReader* reader =
+ serd_reader_new(world,
+ input_syntax ? input_syntax : SERD_TRIG,
+ reader_flags,
+ sink,
+ stack_size);
+ serd_reader_add_blank_prefix(reader, add_prefix);
+
+ SerdNode* name = serd_new_string("string");
+ if (!(st = serd_reader_start_string(reader, input_string, name))) {
+ st = serd_reader_read_document(reader);
+ }
+ serd_node_free(name);
+ serd_reader_free(reader);
}
- if (!st) {
- st = serd_reader_read_document(reader);
+ char** inputs = argv + a;
+ int n_inputs = argc - a;
+ size_t prefix_len = 0;
+ char* prefix = NULL;
+ if (n_inputs > 1) {
+ prefix_len = 8 + strlen(add_prefix);
+ prefix = (char*)calloc(1, prefix_len);
}
- serd_reader_finish(reader);
+ for (int i = 0; i < n_inputs; ++i) {
+ if (!base) {
+ SerdNode* file_uri = serd_new_file_uri(inputs[i], NULL);
+ serd_env_set_base_uri(env, file_uri);
+ serd_node_free(file_uri);
+ }
+
+ if (n_inputs > 1) {
+ snprintf(prefix, prefix_len, "f%d%s", i, add_prefix);
+ }
+
+ if ((st = read_file(world,
+ input_syntax,
+ reader_flags,
+ sink,
+ stack_size,
+ inputs[i],
+ n_inputs > 1 ? prefix : add_prefix,
+ bulk_read))) {
+ break;
+ }
+ }
+ free(prefix);
if (st <= SERD_FAILURE && use_model) {
const SerdSink* wsink = serd_writer_get_sink(writer);
@@ -301,7 +359,6 @@ main(int argc, char** argv)
serd_node_free(input_name);
serd_inserter_free(inserter);
serd_model_free(model);
- serd_reader_free(reader);
serd_writer_free(writer);
serd_byte_sink_free(byte_sink);
serd_env_free(env);
diff --git a/tests/multifile/input1.ttl b/tests/multifile/input1.ttl
new file mode 100644
index 00000000..88c3f8e9
--- /dev/null
+++ b/tests/multifile/input1.ttl
@@ -0,0 +1,2 @@
+[]
+ a <http://example.org/Type> .
diff --git a/tests/multifile/input2.trig b/tests/multifile/input2.trig
new file mode 100644
index 00000000..260080a8
--- /dev/null
+++ b/tests/multifile/input2.trig
@@ -0,0 +1,7 @@
+[]
+ a <http://example.org/Type> .
+
+<http://example.org/graph> {
+ []
+ a <http://example.org/OtherType> .
+}
diff --git a/tests/multifile/output.nq b/tests/multifile/output.nq
new file mode 100644
index 00000000..dd35dc4d
--- /dev/null
+++ b/tests/multifile/output.nq
@@ -0,0 +1,3 @@
+_:f0b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Type> .
+_:f1b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Type> .
+_:f1b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherType> <http://example.org/graph> .
diff --git a/wscript b/wscript
index 2841d323..ac7ec09b 100644
--- a/wscript
+++ b/wscript
@@ -493,7 +493,7 @@ def test(tst):
import tempfile
# Create test output directories
- for i in ['bad', 'good', 'lax', 'terse',
+ for i in ['bad', 'good', 'lax', 'terse', 'multifile',
'TurtleTests', 'NTriplesTests', 'NQuadsTests', 'TriGTests']:
try:
test_dir = os.path.join('tests', i)
@@ -547,6 +547,13 @@ def test(tst):
stdout.seek(0, 2) # Seek to end
check(lambda: stdout.tell() == 0, name='empty output')
+ with tst.group('MultiFile') as check:
+ path = '%s/tests/multifile' % srcdir
+ check([serdi, '%s/input1.ttl' % path, '%s/input2.trig' % path],
+ stdout='tests/multifile/output.out.nq')
+ check.file_equals('%s/tests/multifile/output.nq' % srcdir,
+ 'tests/multifile/output.out.nq')
+
with tst.group('BadCommands', expected=1, stderr=autowaf.NONEMPTY) as check:
check([serdi])
check([serdi, '/no/such/file'])