diff options
-rw-r--r-- | include/serd/serd.h | 14 | ||||
-rw-r--r-- | src/cursor.c | 9 | ||||
-rw-r--r-- | src/describe.c | 180 | ||||
-rw-r--r-- | src/writer.c | 2 | ||||
-rw-r--r-- | test/sort/GOPS.nq | 3 | ||||
-rw-r--r-- | test/sort/GOSP.nq | 3 | ||||
-rw-r--r-- | test/sort/GPSO.nq | 3 | ||||
-rw-r--r-- | test/sort/GSOP.nq | 3 | ||||
-rw-r--r-- | test/sort/GSPO.nq | 3 | ||||
-rw-r--r-- | test/sort/OPS.nq | 3 | ||||
-rw-r--r-- | test/sort/OSP.nq | 3 | ||||
-rw-r--r-- | test/sort/POS.nq | 3 | ||||
-rw-r--r-- | test/sort/PSO.nq | 3 | ||||
-rw-r--r-- | test/sort/SOP.nq | 3 | ||||
-rw-r--r-- | test/sort/SPO.nq | 3 | ||||
-rw-r--r-- | test/sort/input.trig | 27 | ||||
-rw-r--r-- | test/sort/pretty.nq | 3 | ||||
-rw-r--r-- | test/sort/untyped.nq | 12 | ||||
-rwxr-xr-x | test/test_sort.py | 16 | ||||
-rw-r--r-- | tools/console.c | 1 | ||||
-rw-r--r-- | tools/serd-sort.c | 8 |
21 files changed, 214 insertions, 91 deletions
diff --git a/include/serd/serd.h b/include/serd/serd.h index 1f46e092..07f6b9f5 100644 --- a/include/serd/serd.h +++ b/include/serd/serd.h @@ -2523,7 +2523,14 @@ typedef enum { particular invalid UTF-8 text. Note that this flag should be used carefully, since it can result in data loss. */ - SERD_WRITE_LAX = 1u << 4u + SERD_WRITE_LAX = 1u << 4u, + + /** + Write rdf:type as a normal predicate. + + This disables the special "a" syntax in Turtle and TriG. + */ + SERD_WRITE_RDF_TYPE = 1u << 5u } SerdWriterFlag; /// Bitwise OR of SerdWriterFlag values @@ -2629,7 +2636,7 @@ serd_cursor_copy(const SerdCursor* SERD_NULLABLE cursor); /// Return the statement pointed to by `cursor` SERD_API const SerdStatement* SERD_NULLABLE -serd_cursor_get(const SerdCursor* SERD_NONNULL cursor); +serd_cursor_get(const SerdCursor* SERD_NULLABLE cursor); /** Increment cursor to point to the next statement. @@ -2671,7 +2678,8 @@ serd_cursor_free(SerdCursor* SERD_NULLABLE cursor); /// Flags that control the style of a model serialisation typedef enum { - SERD_NO_INLINE_OBJECTS = 1u << 0u ///< Disable object inlining + SERD_NO_INLINE_OBJECTS = 1u << 0u, ///< Disable object inlining + SERD_NO_TYPE_FIRST = 1u << 1u ///< Disable writing rdf:type ("a") first } SerdDescribeFlag; /// Bitwise OR of SerdDescribeFlag values diff --git a/src/cursor.c b/src/cursor.c index 4213476e..650ac771 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -146,11 +146,10 @@ serd_cursor_copy(const SerdCursor* const cursor) const SerdStatement* serd_cursor_get(const SerdCursor* const cursor) { - assert(cursor); - - return ((!zix_btree_iter_is_end(cursor->iter) && check_version(cursor)) - ? (const SerdStatement*)zix_btree_get(cursor->iter) - : NULL); + return ( + (cursor && !zix_btree_iter_is_end(cursor->iter) && check_version(cursor)) + ? (const SerdStatement*)zix_btree_get(cursor->iter) + : NULL); } SerdStatus diff --git a/src/describe.c b/src/describe.c index 718eaf1c..9328f261 100644 --- a/src/describe.c +++ b/src/describe.c @@ -29,17 +29,24 @@ #include <assert.h> #include <stdbool.h> -#include <stdlib.h> +#include <stddef.h> typedef enum { NAMED, ANON_S, ANON_O, LIST_S, LIST_O } NodeStyle; +typedef struct { + const SerdModel* model; // Model to read from + const SerdSink* sink; // Sink to write description to + ZixHash* list_subjects; // Nodes written in the current list or null + SerdDescribeFlags flags; // Flags to control description +} DescribeContext; + static SerdStatus -write_range_statement(const SerdSink* sink, - const SerdModel* model, - ZixHash* list_subjects, - unsigned depth, - SerdStatementFlags flags, - const SerdStatement* statement); +write_range_statement(const DescribeContext* ctx, + unsigned depth, + SerdStatementFlags statement_flags, + const SerdStatement* statement, + const SerdNode* last_subject, + bool write_types); static NodeStyle get_node_style(const SerdModel* const model, const SerdNode* const node) @@ -81,39 +88,41 @@ ptr_equals(const SerdNode* const a, const SerdNode* const b) } static SerdStatus -write_pretty_range(const SerdSink* const sink, - const unsigned depth, - const SerdModel* const model, - SerdCursor* const range) +write_pretty_range(const DescribeContext* const ctx, + const unsigned depth, + SerdCursor* const range, + const SerdNode* last_subject, + bool write_types) { - ZixHash* const list_subjects = zix_hash_new(identity, ptr_hash, ptr_equals); - SerdStatus st = SERD_SUCCESS; - - while (!st && !serd_cursor_is_end(range)) { - const SerdStatement* const statement = serd_cursor_get(range); - assert(statement); + SerdStatus st = SERD_SUCCESS; + const SerdStatement* statement = serd_cursor_get(range); - if (!(st = write_range_statement( - sink, model, list_subjects, depth, 0, statement))) { - st = serd_cursor_advance(range); + while (statement) { + // Write this statement (and possibly more to describe anonymous nodes) + if ((st = write_range_statement( + ctx, depth, 0u, statement, last_subject, write_types))) { + break; } - } - zix_hash_free(list_subjects); + // Update the last subject and advance the cursor + last_subject = serd_statement_subject(statement); + st = serd_cursor_advance(range); + statement = serd_cursor_get(range); + } return st > SERD_FAILURE ? st : SERD_SUCCESS; } static SerdStatus -write_list(const SerdSink* const sink, - const SerdModel* const model, - ZixHash* const list_subjects, - const unsigned depth, - SerdStatementFlags flags, - const SerdNode* object, - const SerdNode* const graph) +write_list(const DescribeContext* const ctx, + const unsigned depth, + SerdStatementFlags flags, + const SerdNode* object, + const SerdNode* const graph) { + const SerdModel* const model = ctx->model; const SerdWorld* const world = model->world; + const SerdSink* const sink = ctx->sink; const SerdNode* const rdf_first = world->rdf_first; const SerdNode* const rdf_rest = world->rdf_rest; const SerdNode* const rdf_nil = world->rdf_nil; @@ -126,8 +135,7 @@ write_list(const SerdSink* const sink, while (!st && !serd_node_equals(object, rdf_nil)) { // Write rdf:first statement for this node - if ((st = write_range_statement( - sink, model, list_subjects, depth, flags, fs))) { + if ((st = write_range_statement(ctx, depth, flags, fs, NULL, false))) { return st; } @@ -177,24 +185,47 @@ skip_range_statement(const SerdModel* const model, } static SerdStatus -write_range_statement(const SerdSink* const sink, - const SerdModel* const model, - ZixHash* const list_subjects, - const unsigned depth, - SerdStatementFlags flags, - const SerdStatement* SERD_NONNULL statement) +write_subject_types(const DescribeContext* const ctx, + const unsigned depth, + const SerdNode* const subject, + const SerdNode* const graph) { - const SerdNode* const subject = serd_statement_subject(statement); - const NodeStyle subject_style = get_node_style(model, subject); - const SerdNode* const object = serd_statement_object(statement); - const NodeStyle object_style = get_node_style(model, object); - const SerdNode* const graph = serd_statement_graph(statement); - SerdStatus st = SERD_SUCCESS; + SerdStatus st = SERD_SUCCESS; + SerdCursor* const t = serd_model_find( + ctx->model, subject, ctx->model->world->rdf_type, NULL, graph); - if (subject_style == ANON_S) { // Write anonymous subject like "[] p o" - flags |= SERD_EMPTY_S; + if (t) { + st = write_pretty_range(ctx, depth + 1, t, subject, true); } + serd_cursor_free(t); + return st; +} + +static bool +types_first_for_subject(const DescribeContext* const ctx, const NodeStyle style) +{ + return style != LIST_S && !(ctx->flags & SERD_NO_TYPE_FIRST); +} + +static SerdStatus +write_range_statement(const DescribeContext* const ctx, + const unsigned depth, + SerdStatementFlags statement_flags, + const SerdStatement* SERD_NONNULL statement, + const SerdNode* SERD_NULLABLE last_subject, + const bool write_types) +{ + const SerdModel* const model = ctx->model; + const SerdSink* const sink = ctx->sink; + const SerdNode* const subject = serd_statement_subject(statement); + const NodeStyle subject_style = get_node_style(model, subject); + const SerdNode* const predicate = serd_statement_predicate(statement); + const SerdNode* const object = serd_statement_object(statement); + const NodeStyle object_style = get_node_style(model, object); + const SerdNode* const graph = serd_statement_graph(statement); + SerdStatus st = SERD_SUCCESS; + if (depth == 0u) { if (skip_range_statement(model, statement)) { return SERD_SUCCESS; // Skip subject that will be inlined elsewhere @@ -202,9 +233,8 @@ write_range_statement(const SerdSink* const sink, if (subject_style == LIST_S) { // First write inline list subject, which this statement will follow - if (zix_hash_insert(list_subjects, subject) != ZIX_STATUS_EXISTS) { - st = write_list( - sink, model, list_subjects, 2, flags | SERD_LIST_S, subject, graph); + if (zix_hash_insert(ctx->list_subjects, subject) != ZIX_STATUS_EXISTS) { + st = write_list(ctx, 2, statement_flags | SERD_LIST_S, subject, graph); } } } @@ -213,29 +243,42 @@ write_range_statement(const SerdSink* const sink, return st; } - if (object_style == ANON_O) { // Write anonymous object like "[ ... ]" - SerdCursor* const iter = serd_model_find(model, object, NULL, NULL, NULL); + // If this is a new subject, write types first if necessary + const bool types_first = types_first_for_subject(ctx, subject_style); + if (subject != last_subject && types_first) { + st = write_subject_types(ctx, depth, subject, graph); + } - flags |= SERD_ANON_O; - if (!(st = serd_sink_write_statement(sink, flags, statement))) { - if (!(st = write_pretty_range(sink, depth + 1, model, iter))) { - st = serd_sink_write_end(sink, object); - } - } + // Skip type statement if it would be written another time (just above) + if (subject_style != LIST_S && !write_types && + serd_node_equals(predicate, model->world->rdf_type)) { + return st; + } - serd_cursor_free(iter); + // Set up the flags for this statement + statement_flags |= + (((subject_style == ANON_S) * (SerdStatementFlags)SERD_EMPTY_S) | + ((object_style == ANON_O) * (SerdStatementFlags)SERD_ANON_O) | + ((object_style == LIST_O) * (SerdStatementFlags)SERD_LIST_O)); - } else if (object_style == LIST_O) { // Write list object like "( ... )" - if (!(st = - serd_sink_write_statement(sink, flags | SERD_LIST_O, statement))) { - flags = flags & ~((unsigned)SERD_LIST_S); + // Finally write this statement + if ((st = serd_sink_write_statement(sink, statement_flags, statement))) { + return st; + } - st = - write_list(sink, model, list_subjects, depth + 1, flags, object, graph); + if (object_style == ANON_O) { + // Follow an anonymous object with its description like "[ ... ]" + SerdCursor* const iter = serd_model_find(model, object, NULL, NULL, NULL); + + if (!(st = write_pretty_range(ctx, depth + 1, iter, last_subject, false))) { + st = serd_sink_write_end(sink, object); } - } else { - st = serd_sink_write_statement(sink, flags, statement); + serd_cursor_free(iter); + + } else if (object_style == LIST_O) { + // Follow a list object with its description like "( ... )" + st = write_list(ctx, depth + 1, 0u, object, graph); } return st; @@ -264,7 +307,12 @@ serd_describe_range(const SerdCursor* const range, } } } else { - st = write_pretty_range(sink, 0, range->model, ©); + DescribeContext ctx = { + range->model, sink, zix_hash_new(identity, ptr_hash, ptr_equals), flags}; + + st = write_pretty_range(&ctx, 0, ©, NULL, (flags & SERD_NO_TYPE_FIRST)); + + zix_hash_free(ctx.list_subjects); } return st; diff --git a/src/writer.c b/src/writer.c index 30e09a4f..b7814158 100644 --- a/src/writer.c +++ b/src/writer.c @@ -841,7 +841,7 @@ write_uri_node(SerdWriter* const writer, const char* node_str = serd_node_string(node); const bool has_scheme = serd_uri_string_has_scheme(node_str); if (supports_abbrev(writer)) { - if (field == SERD_PREDICATE && + if (!(writer->flags & SERD_WRITE_RDF_TYPE) && field == SERD_PREDICATE && serd_node_equals(node, writer->world->rdf_type)) { return esink("a", 1, writer); } diff --git a/test/sort/GOPS.nq b/test/sort/GOPS.nq index c7472e03..3d033b6e 100644 --- a/test/sort/GOPS.nq +++ b/test/sort/GOPS.nq @@ -1,10 +1,13 @@ _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "1"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "2"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . <http://example.org/s> <http://example.org/literal> "s1" <http://example.org/graph1> . +_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Anonymous> <http://example.org/graph1> . +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/aProperty> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/orAnother> <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://example.org/graph1> . <http://example.org/s> <http://example.org/blank> _:b1 <http://example.org/graph1> . <http://example.org/s> <http://example.org/list> _:b2 <http://example.org/graph1> . _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b3 <http://example.org/graph1> . +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/graph2> . diff --git a/test/sort/GOSP.nq b/test/sort/GOSP.nq index c7472e03..3d033b6e 100644 --- a/test/sort/GOSP.nq +++ b/test/sort/GOSP.nq @@ -1,10 +1,13 @@ _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "1"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "2"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . <http://example.org/s> <http://example.org/literal> "s1" <http://example.org/graph1> . +_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Anonymous> <http://example.org/graph1> . +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/aProperty> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/orAnother> <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://example.org/graph1> . <http://example.org/s> <http://example.org/blank> _:b1 <http://example.org/graph1> . <http://example.org/s> <http://example.org/list> _:b2 <http://example.org/graph1> . _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b3 <http://example.org/graph1> . +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/graph2> . diff --git a/test/sort/GPSO.nq b/test/sort/GPSO.nq index 1a858017..67e13aa7 100644 --- a/test/sort/GPSO.nq +++ b/test/sort/GPSO.nq @@ -7,4 +7,7 @@ _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "1"^^<http://www.w3.org/ _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "2"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b3 <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://example.org/graph1> . +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . +_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Anonymous> <http://example.org/graph1> . <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/graph2> . +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . diff --git a/test/sort/GSOP.nq b/test/sort/GSOP.nq index fc073a00..dbfcb7c1 100644 --- a/test/sort/GSOP.nq +++ b/test/sort/GSOP.nq @@ -1,10 +1,13 @@ <http://example.org/s> <http://example.org/literal> "s1" <http://example.org/graph1> . +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . <http://example.org/s> <http://example.org/blank> _:b1 <http://example.org/graph1> . <http://example.org/s> <http://example.org/list> _:b2 <http://example.org/graph1> . +_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Anonymous> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/aProperty> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/orAnother> <http://example.org/graph1> . _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "1"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b3 <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "2"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://example.org/graph1> . +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/graph2> . diff --git a/test/sort/GSPO.nq b/test/sort/GSPO.nq index 726b1d42..5aab6e1e 100644 --- a/test/sort/GSPO.nq +++ b/test/sort/GSPO.nq @@ -1,10 +1,13 @@ <http://example.org/s> <http://example.org/blank> _:b1 <http://example.org/graph1> . <http://example.org/s> <http://example.org/list> _:b2 <http://example.org/graph1> . <http://example.org/s> <http://example.org/literal> "s1" <http://example.org/graph1> . +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/aProperty> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/orAnother> <http://example.org/graph1> . +_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Anonymous> <http://example.org/graph1> . _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "1"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b3 <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "2"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://example.org/graph1> . <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/graph2> . +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . diff --git a/test/sort/OPS.nq b/test/sort/OPS.nq index 456ade7f..593760be 100644 --- a/test/sort/OPS.nq +++ b/test/sort/OPS.nq @@ -1,6 +1,9 @@ _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "1"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "2"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . <http://example.org/s> <http://example.org/literal> "s1" <http://example.org/graph1> . +_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Anonymous> <http://example.org/graph1> . +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/aProperty> <http://example.org/graph1> . <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/graph2> . _:b1 <http://example.org/with> <http://example.org/orAnother> <http://example.org/graph1> . diff --git a/test/sort/OSP.nq b/test/sort/OSP.nq index 456ade7f..593760be 100644 --- a/test/sort/OSP.nq +++ b/test/sort/OSP.nq @@ -1,6 +1,9 @@ _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "1"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "2"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . <http://example.org/s> <http://example.org/literal> "s1" <http://example.org/graph1> . +_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Anonymous> <http://example.org/graph1> . +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/aProperty> <http://example.org/graph1> . <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/graph2> . _:b1 <http://example.org/with> <http://example.org/orAnother> <http://example.org/graph1> . diff --git a/test/sort/POS.nq b/test/sort/POS.nq index 51c675de..20eabfe1 100644 --- a/test/sort/POS.nq +++ b/test/sort/POS.nq @@ -8,3 +8,6 @@ _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "1"^^<http://www.w3.org/ _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "2"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://example.org/graph1> . _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b3 <http://example.org/graph1> . +_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Anonymous> <http://example.org/graph1> . +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . diff --git a/test/sort/PSO.nq b/test/sort/PSO.nq index 0fb7bd68..113dd549 100644 --- a/test/sort/PSO.nq +++ b/test/sort/PSO.nq @@ -8,3 +8,6 @@ _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "1"^^<http://www.w3.org/ _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "2"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b3 <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://example.org/graph1> . +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . +_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Anonymous> <http://example.org/graph1> . diff --git a/test/sort/SOP.nq b/test/sort/SOP.nq index 1692689c..7867eb24 100644 --- a/test/sort/SOP.nq +++ b/test/sort/SOP.nq @@ -1,7 +1,10 @@ +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/graph2> . <http://example.org/s> <http://example.org/literal> "s1" <http://example.org/graph1> . +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . <http://example.org/s> <http://example.org/blank> _:b1 <http://example.org/graph1> . <http://example.org/s> <http://example.org/list> _:b2 <http://example.org/graph1> . +_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Anonymous> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/aProperty> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/orAnother> <http://example.org/graph1> . _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "1"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . diff --git a/test/sort/SPO.nq b/test/sort/SPO.nq index 508debc7..2b09a976 100644 --- a/test/sort/SPO.nq +++ b/test/sort/SPO.nq @@ -1,9 +1,12 @@ <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/graph2> . +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . <http://example.org/s> <http://example.org/blank> _:b1 <http://example.org/graph1> . <http://example.org/s> <http://example.org/list> _:b2 <http://example.org/graph1> . <http://example.org/s> <http://example.org/literal> "s1" <http://example.org/graph1> . +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/aProperty> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/orAnother> <http://example.org/graph1> . +_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Anonymous> <http://example.org/graph1> . _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "1"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b3 <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "2"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . diff --git a/test/sort/input.trig b/test/sort/input.trig index 154a9fb8..9561d9b8 100644 --- a/test/sort/input.trig +++ b/test/sort/input.trig @@ -1,19 +1,22 @@ @prefix eg: <http://example.org/> . eg:graph1 { -eg:s - eg:blank [ - eg:with eg:aProperty , - eg:orAnother - ] ; - eg:list ( - 1 - 2 - ) ; - eg:literal "s1" . + eg:s + a eg:Subject ; + eg:blank [ + a eg:Anonymous ; + eg:with eg:aProperty , + eg:orAnother + ] ; + eg:list ( + 1 + 2 + ) ; + eg:literal "s1" . } eg:graph2 { -eg:a - eg:b eg:c . + eg:a + a eg:OtherSubject ; + eg:b eg:c . } diff --git a/test/sort/pretty.nq b/test/sort/pretty.nq index 451247d4..97851b82 100644 --- a/test/sort/pretty.nq +++ b/test/sort/pretty.nq @@ -1,4 +1,6 @@ +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . <http://example.org/s> <http://example.org/blank> _:b1 <http://example.org/graph1> . +_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Anonymous> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/aProperty> <http://example.org/graph1> . _:b1 <http://example.org/with> <http://example.org/orAnother> <http://example.org/graph1> . <http://example.org/s> <http://example.org/list> _:b2 <http://example.org/graph1> . @@ -7,4 +9,5 @@ _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b3 <http://example.org/ _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "2"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://example.org/graph1> . <http://example.org/s> <http://example.org/literal> "s1" <http://example.org/graph1> . +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/graph2> . diff --git a/test/sort/untyped.nq b/test/sort/untyped.nq new file mode 100644 index 00000000..74625d7d --- /dev/null +++ b/test/sort/untyped.nq @@ -0,0 +1,12 @@ +<http://example.org/s> <http://example.org/blank> _:b1 <http://example.org/graph1> . +_:b1 <http://example.org/with> <http://example.org/aProperty> <http://example.org/graph1> . +_:b1 <http://example.org/with> <http://example.org/orAnother> <http://example.org/graph1> . +<http://example.org/s> <http://example.org/list> _:b2 <http://example.org/graph1> . +_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "1"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . +_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b3 <http://example.org/graph1> . +_:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "2"^^<http://www.w3.org/2001/XMLSchema#integer> <http://example.org/graph1> . +_:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://example.org/graph1> . +<http://example.org/s> <http://example.org/literal> "s1" <http://example.org/graph1> . +<http://example.org/s> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Subject> <http://example.org/graph1> . +<http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/graph2> . +<http://example.org/a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherSubject> <http://example.org/graph2> . diff --git a/test/test_sort.py b/test/test_sort.py index 4080b93c..04c8ba10 100755 --- a/test/test_sort.py +++ b/test/test_sort.py @@ -28,15 +28,17 @@ collations = [ ] -def check(test_dir, command_prefix, out_dir, input_path, name): +def check(test_dir, command_prefix, out_dir, input_path, name, flags=None): """Sort a single input in the named order and check the output. - The expected output is assumed to exist at test_dir/NAME.nq. + The expected output is assumed to exist at test_dir/NAME.untyped.nq. """ output_path = os.path.join(out_dir, name + ".nq") result_path = os.path.join(test_dir, name + ".nq") - options = [] if name == "pretty" else ["-c", name] + options = flags if flags is not None else [] + if name not in ["pretty", "untyped"]: + options += ["-c", name] # Randomly add irrelevant options just to cover them if random.choice([True, False]): @@ -68,10 +70,18 @@ def run_tests(test_dir, command_prefix, out_dir): input_trig = os.path.join(test_dir, "input.trig") n_failures = 0 + + # Test all the basic collations, and "pretty" with type first for name in collations: if not check(test_dir, command_prefix, out_dir, input_trig, name): n_failures += 1 + # Test "pretty" without type first + if not check( + test_dir, command_prefix, out_dir, input_trig, "untyped", ["-t"] + ): + n_failures += 1 + return n_failures diff --git a/tools/console.c b/tools/console.c index f1e78d75..d7f67c35 100644 --- a/tools/console.c +++ b/tools/console.c @@ -218,6 +218,7 @@ serd_set_output_option(const SerdStringView name, {"verbatim", SERD_WRITE_VERBATIM}, {"terse", SERD_WRITE_TERSE}, {"lax", SERD_WRITE_LAX}, + {"rdf_type", SERD_WRITE_RDF_TYPE}, {NULL, SERD_WRITE_ASCII}, }; diff --git a/tools/serd-sort.c b/tools/serd-sort.c index 8ba99445..5e71e95e 100644 --- a/tools/serd-sort.c +++ b/tools/serd-sort.c @@ -176,7 +176,8 @@ print_usage(const char* const name, const bool error) " -c COLLATION An optional \"G\" then the letters \"SPO\" in any order.\n" " -h Display this help and exit.\n" " -k BYTES Parser stack size.\n" - " -o FILENAME Write output to FILENAME instead of stdout.\n"; + " -o FILENAME Write output to FILENAME instead of stdout.\n" + " -t Do not write type as \"a\" before other properties.\n"; FILE* const os = error ? stderr : stdout; fprintf(os, "%s", error ? "\n" : ""); @@ -221,6 +222,11 @@ parse_option(OptionIter* const iter, Options* const opts) case 's': return serd_get_argument(iter, &opts->input_string); + case 't': + opts->common.output.flags |= SERD_WRITE_RDF_TYPE; + opts->flags |= SERD_NO_TYPE_FIRST; + return serd_option_iter_advance(iter); + default: break; } |