diff options
-rw-r--r-- | doc/man/serdi.1 | 15 | ||||
-rw-r--r-- | include/serd/syntax.h | 15 | ||||
-rw-r--r-- | src/serdi.c | 16 | ||||
-rw-r--r-- | src/syntax.c | 8 | ||||
-rw-r--r-- | src/writer.c | 6 | ||||
-rw-r--r-- | test/meson.build | 10 | ||||
-rwxr-xr-x | test/test_empty.py | 25 | ||||
-rw-r--r-- | test/test_writer.c | 33 |
8 files changed, 107 insertions, 21 deletions
diff --git a/doc/man/serdi.1 b/doc/man/serdi.1 index f03fe23d..7822832a 100644 --- a/doc/man/serdi.1 +++ b/doc/man/serdi.1 @@ -71,6 +71,7 @@ Case is ignored, valid values are: .Dq NQuads , .Dq NTriples , .Dq TriG , +and .Dq Turtle . .It Fl k Ar bytes Parser stack size. @@ -86,10 +87,16 @@ Note that data may be lost when using this option. Write output as .Ar syntax . Case is ignored, valid values are: +.Dq empty , .Dq NQuads , .Dq NTriples , .Dq TriG , +and .Dq Turtle . +The +.Cm empty +syntax suppresses the output, +so that only warnings and errors will be printed. .It Fl p Ar prefix Add .Ar prefix @@ -153,10 +160,10 @@ exits with a status of 0, or non-zero if an error occurred. .Pa file.ttl > .Pa out.ttl -.It Print any errors: -.Nm Pa file.ttl -> -.Pa /dev/null +.It Print only errors and discard the output: +.Nm Fl O +.Ar empty +.Pa input.ttl .El .Sh SEE ALSO .Bl -item -compact diff --git a/include/serd/syntax.h b/include/serd/syntax.h index c3a33ff5..62ba6571 100644 --- a/include/serd/syntax.h +++ b/include/serd/syntax.h @@ -18,17 +18,20 @@ SERD_BEGIN_DECLS /// Syntax supported by serd typedef enum { - SERD_TURTLE = 1U, ///< Terse triples http://www.w3.org/TR/turtle - SERD_NTRIPLES = 2U, ///< Line-based triples http://www.w3.org/TR/n-triples/ - SERD_NQUADS = 3U, ///< Line-based quads http://www.w3.org/TR/n-quads/ - SERD_TRIG = 4U, ///< Terse quads http://www.w3.org/TR/trig/ + SERD_SYNTAX_EMPTY = 0U, ///< Empty syntax + SERD_TURTLE = 1U, ///< Terse triples http://www.w3.org/TR/turtle/ + SERD_NTRIPLES = 2U, ///< Flat triples http://www.w3.org/TR/n-triples/ + SERD_NQUADS = 3U, ///< Flat quads http://www.w3.org/TR/n-quads/ + SERD_TRIG = 4U, ///< Terse quads http://www.w3.org/TR/trig/ } SerdSyntax; /** Get a syntax by name. - Case-insensitive, supports "Turtle", "NTriples", "NQuads", and "TriG". Zero - is returned if the name is not recognized. + Case-insensitive, supports "Turtle", "NTriples", "NQuads", and "TriG". + + @return The syntax with the given name, or the empty syntax if the name is + unknown. */ SERD_PURE_API SerdSyntax serd_syntax_by_name(const char* SERD_NONNULL name); diff --git a/src/serdi.c b/src/serdi.c index 75599ac7..8a4a52cf 100644 --- a/src/serdi.c +++ b/src/serdi.c @@ -65,7 +65,7 @@ print_usage(const char* const name, const bool error) " -i SYNTAX Input syntax: turtle/ntriples/trig/nquads.\n" " -k BYTES Parser stack size.\n" " -l Lax (non-strict) parsing.\n" - " -o SYNTAX Output syntax: turtle/ntriples/nquads.\n" + " -o SYNTAX Output syntax: empty/turtle/ntriples/nquads.\n" " -p PREFIX Add PREFIX to blank node IDs.\n" " -q Suppress all output except data.\n" " -r ROOT_URI Keep relative URIs within ROOT_URI.\n" @@ -100,13 +100,14 @@ main(int argc, char** argv) { const char* const prog = argv[0]; - SerdSyntax input_syntax = (SerdSyntax)0; - SerdSyntax output_syntax = (SerdSyntax)0; + SerdSyntax input_syntax = SERD_SYNTAX_EMPTY; + SerdSyntax output_syntax = SERD_SYNTAX_EMPTY; SerdWriterFlags writer_flags = 0; bool from_string = false; bool from_stdin = false; bool bulk_read = true; bool lax = false; + bool osyntax_set = false; bool quiet = false; size_t stack_size = 1048576U; const char* add_prefix = NULL; @@ -182,12 +183,15 @@ main(int argc, char** argv) stack_size = (size_t)size; break; } else if (opt == 'o') { + osyntax_set = true; if (argv[a][o + 1] || ++a == argc) { return missing_arg(prog, 'o'); } - if (!(output_syntax = serd_syntax_by_name(argv[a]))) { - return print_usage(prog, true); + if (!strcmp(argv[a], "empty")) { + output_syntax = SERD_SYNTAX_EMPTY; + } else if (!(output_syntax = serd_syntax_by_name(argv[a]))) { + return print_usage(argv[0], true); } break; } else if (opt == 'p') { @@ -228,7 +232,7 @@ main(int argc, char** argv) } const bool input_has_graphs = serd_syntax_has_graphs(input_syntax); - if (!output_syntax) { + if (!output_syntax && !osyntax_set) { output_syntax = input_has_graphs ? SERD_NQUADS : SERD_NTRIPLES; } diff --git a/src/syntax.c b/src/syntax.c index 1599df08..d75865b1 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -19,7 +19,7 @@ static const Syntax syntaxes[] = { {"ntriples", ".nt", SERD_NTRIPLES}, {"nquads", ".nq", SERD_NQUADS}, {"trig", ".trig", SERD_TRIG}, - {NULL, NULL, (SerdSyntax)0}, + {NULL, NULL, SERD_SYNTAX_EMPTY}, }; SerdSyntax @@ -33,7 +33,7 @@ serd_syntax_by_name(const char* const name) } } } - return (SerdSyntax)0; + return SERD_SYNTAX_EMPTY; } SerdSyntax @@ -43,12 +43,12 @@ serd_guess_syntax(const char* const filename) if (ext && ext[1]) { const size_t ext_len = strlen(ext); for (const Syntax* s = syntaxes; s->name; ++s) { - if (!serd_strncasecmp(s->extension, ext, ext_len)) { + if (s->extension && !serd_strncasecmp(s->extension, ext, ext_len)) { return s->syntax; } } } - return (SerdSyntax)0; + return SERD_SYNTAX_EMPTY; } bool diff --git a/src/writer.c b/src/writer.c index 5603e9ca..a1d91ff8 100644 --- a/src/writer.c +++ b/src/writer.c @@ -1003,6 +1003,10 @@ serd_writer_write_statement(SerdWriter* const writer, assert(!((flags & SERD_ANON_O) && (flags & SERD_LIST_O))); assert(!((flags & SERD_EMPTY_O) && (flags & SERD_LIST_O))); + if (writer->syntax == SERD_SYNTAX_EMPTY) { + return SERD_SUCCESS; + } + SerdStatus st = SERD_SUCCESS; const SerdNode* const subject = serd_statement_subject(statement); const SerdNode* const predicate = serd_statement_predicate(statement); @@ -1149,7 +1153,7 @@ serd_writer_end_anon(SerdWriter* writer, const SerdNode* node) { SerdStatus st = SERD_SUCCESS; - if (writer->syntax == SERD_NTRIPLES || writer->syntax == SERD_NQUADS) { + if (writer->syntax != SERD_TURTLE && writer->syntax != SERD_TRIG) { return SERD_SUCCESS; } diff --git a/test/meson.build b/test/meson.build index 2ed73e63..97e082e0 100644 --- a/test/meson.build +++ b/test/meson.build @@ -16,6 +16,7 @@ simple_script_paths = [ '../scripts/check_formatting.py', 'serd_test_util/__init__.py', 'run_suite.py', + 'test_empty.py', 'test_quiet.py', 'test_stdin.py', 'test_write_error.py', @@ -256,6 +257,15 @@ if is_variable('serdi') suite: input_suite, ) + # Output + + test( + 'empty', + files('test_empty.py'), + args: script_args + [serd_ttl], + env: test_env, + suite: 'output', + ) # IO errors diff --git a/test/test_empty.py b/test/test_empty.py new file mode 100755 index 00000000..3cd5517b --- /dev/null +++ b/test/test_empty.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Copyright 2022-2023 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: ISC + +"""Test writing empty output.""" + +# pylint: disable=duplicate-code + +import shlex +import subprocess +import tempfile + +import serd_test_util as util + +args = util.wrapper_args(__doc__, True) +command = shlex.split(args.wrapper) + [args.serdi, "-o", "empty", args.input] + +with tempfile.TemporaryFile() as out: + proc = subprocess.run(command, check=False, stdout=out) + + out.seek(0, 2) # Seek to end + + assert proc.returncode == 0 + assert out.tell() == 0 diff --git a/test/test_writer.c b/test/test_writer.c index 1334bb02..6066b6e3 100644 --- a/test/test_writer.c +++ b/test/test_writer.c @@ -293,6 +293,38 @@ test_writer_stack_overflow(void) serd_world_free(world); } +static void +test_write_empty_syntax(void) +{ + SerdWorld* world = serd_world_new(); + SerdEnv* env = serd_env_new(serd_empty_string()); + + SerdNode* s = serd_new_uri(serd_string("http://example.org/s")); + SerdNode* p = serd_new_uri(serd_string("http://example.org/p")); + SerdNode* o = serd_new_curie(serd_string("eg:o")); + + SerdBuffer buffer = {NULL, 0}; + + SerdWriter* writer = serd_writer_new( + world, SERD_SYNTAX_EMPTY, 0U, env, serd_buffer_sink, &buffer); + + assert(writer); + + assert(!serd_sink_write(serd_writer_sink(writer), 0U, s, p, o, NULL)); + + char* out = serd_buffer_sink_finish(&buffer); + + assert(strlen(out) == 0); + serd_free(out); + + serd_writer_free(writer); + serd_node_free(o); + serd_node_free(p); + serd_node_free(s); + serd_env_free(env); + serd_world_free(world); +} + int main(void) { @@ -303,6 +335,7 @@ main(void) test_strict_write(); test_write_error(); test_writer_stack_overflow(); + test_write_empty_syntax(); return 0; } |