diff options
Diffstat (limited to 'src/writer.c')
-rw-r--r-- | src/writer.c | 57 |
1 files changed, 43 insertions, 14 deletions
diff --git a/src/writer.c b/src/writer.c index 19ce926b..3079cebc 100644 --- a/src/writer.c +++ b/src/writer.c @@ -73,8 +73,11 @@ typedef enum { SEP_ANON_S_P, ///< Between anonymous subject and predicate (whitespace) SEP_ANON_END, ///< End of anonymous node (']') SEP_LIST_BEGIN, ///< Start of list ('(') - SEP_LIST_SEP, ///< List separator (whitespace) + SEP_LIST_SEP, ///< List separator (newline) SEP_LIST_END, ///< End of list (')') + SEP_TLIST_BEGIN, ///< Start of terse list ('(') + SEP_TLIST_SEP, ///< Terse list separator (space) + SEP_TLIST_END, ///< End of terse list (')') SEP_GRAPH_BEGIN, ///< Start of graph ('{') SEP_GRAPH_END, ///< End of graph ('}') } Sep; @@ -97,7 +100,7 @@ static const SepRule rules[] = { {NIL, +0, SEP_NONE, SEP_NONE, SEP_NONE}, {NIL, +0, SEP_NONE, SEP_NONE, SEP_NONE}, {'\n', 0, SEP_NONE, SEP_NONE, SEP_NONE}, - {'.', +0, SEP_EACH, SEP_NONE, SEP_EACH}, + {'.', +0, SEP_EACH, SEP_NONE, SEP_NONE}, {'.', +0, SEP_EACH, SEP_NONE, SEP_NONE}, {';', +0, SEP_EACH, SEP_NONE, SEP_EACH}, {',', +0, SEP_EACH, SEP_NONE, SEP_EACH}, @@ -106,12 +109,15 @@ static const SepRule rules[] = { {',', +0, SEP_EACH, SEP_NONE, SEP_NONE}, {NIL, +1, SEP_NONE, SEP_NONE, SEP_EACH}, {' ', +0, SEP_NONE, SEP_NONE, SEP_NONE}, - {'[', +1, M(SEP_JOIN_O_AA), SEP_NONE, SEP_NONE}, + {'[', +1, M(SEP_JOIN_O_AA), M(SEP_TLIST_BEGIN) | M(SEP_TLIST_SEP), SEP_NONE}, {NIL, +1, SEP_NONE, SEP_NONE, M(SEP_ANON_BEGIN)}, {']', -1, SEP_NONE, ~M(SEP_ANON_BEGIN), SEP_NONE}, {'(', +1, M(SEP_JOIN_O_AA), SEP_NONE, SEP_EACH}, {NIL, +0, SEP_NONE, SEP_EACH, SEP_NONE}, {')', -1, SEP_NONE, SEP_EACH, SEP_NONE}, + {'(', +1, SEP_NONE, SEP_NONE, SEP_NONE}, + {NIL, +0, SEP_EACH, SEP_NONE, SEP_NONE}, + {')', -1, SEP_NONE, SEP_NONE, SEP_NONE}, {'{', +1, SEP_EACH, SEP_NONE, SEP_EACH}, {'}', -1, SEP_NONE, SEP_NONE, SEP_EACH}, }; @@ -582,10 +588,14 @@ uri_sink(const void* buf, size_t size, size_t nmemb, void* stream) } SERD_NODISCARD static SerdStatus -write_newline(SerdWriter* writer) +write_newline(SerdWriter* writer, bool terse) { SerdStatus st = SERD_SUCCESS; + if (terse || (writer->flags & SERD_WRITE_TERSE)) { + return esink(" ", 1, writer); + } + TRY(st, esink("\n", 1, writer)); for (int i = 0; i < writer->indent; ++i) { TRY(st, esink("\t", 1, writer)); @@ -595,16 +605,29 @@ write_newline(SerdWriter* writer) } SERD_NODISCARD static SerdStatus -write_sep(SerdWriter* writer, const SerdStatementFlags flags, Sep sep) +write_top_level_sep(SerdWriter* writer) { - (void)flags; + return (writer->last_sep && !(writer->flags & SERD_WRITE_TERSE)) + ? write_newline(writer, false) + : SERD_SUCCESS; +} +SERD_NODISCARD static SerdStatus +write_sep(SerdWriter* writer, const SerdStatementFlags flags, Sep sep) +{ SerdStatus st = SERD_SUCCESS; const SepRule* const rule = &rules[sep]; const bool pre_line = (rule->pre_line_after & (1U << writer->last_sep)); const bool post_line = (rule->post_line_after & (1U << writer->last_sep)); + const bool terse = (((flags & SERD_TERSE_S) && (flags & SERD_LIST_S)) || + ((flags & SERD_TERSE_O) && (flags & SERD_LIST_O))); + + if (terse && sep >= SEP_LIST_BEGIN && sep <= SEP_LIST_END) { + sep = (Sep)((int)sep + 3); // Switch to corresponding terse separator + } + // Adjust indent, but tolerate if it would become negative if (rule->indent && (pre_line || post_line)) { writer->indent = ((rule->indent >= 0 || writer->indent >= -rule->indent) @@ -620,7 +643,7 @@ write_sep(SerdWriter* writer, const SerdStatementFlags flags, Sep sep) // Write newline or space before separator if necessary if (pre_line) { - TRY(st, write_newline(writer)); + TRY(st, write_newline(writer, terse)); } else if (rule->pre_space_after & (1U << writer->last_sep)) { TRY(st, esink(" ", 1, writer)); } @@ -632,18 +655,20 @@ write_sep(SerdWriter* writer, const SerdStatementFlags flags, Sep sep) // Write newline after separator if necessary if (post_line) { - TRY(st, write_newline(writer)); + TRY(st, write_newline(writer, terse)); if (rule->post_line_after != ~(SepMask)0U) { writer->last_sep = SEP_NEWLINE; } } // Reset context and write a blank line after ends of subjects - if (sep == SEP_END_S) { + if (sep == SEP_END_S || sep == SEP_END_DIRECT) { writer->indent = ctx(writer, SERD_GRAPH) ? 1 : 0; writer->context.predicates = false; writer->context.comma_indented = false; - TRY(st, esink("\n", 1, writer)); + if (!terse) { + TRY(st, esink("\n", 1, writer)); + } } writer->last_sep = sep; @@ -987,8 +1012,10 @@ serd_writer_write_statement(SerdWriter* const writer, const SerdNode* const graph = serd_statement_graph(statement); if (!is_resource(subject) || !is_resource(predicate) || !object || - ((flags & SERD_ANON_S) && (flags & SERD_LIST_S)) || - ((flags & SERD_ANON_O) && (flags & SERD_LIST_O))) { + ((flags & SERD_ANON_S) && (flags & SERD_LIST_S)) || // Nonsense + ((flags & SERD_ANON_O) && (flags & SERD_LIST_O)) || // Nonsense + ((flags & SERD_ANON_S) && (flags & SERD_TERSE_S)) || // Unsupported + ((flags & SERD_ANON_O) && (flags & SERD_TERSE_O))) { // Unsupported return SERD_BAD_ARG; } @@ -1013,7 +1040,7 @@ serd_writer_write_statement(SerdWriter* const writer, TRY(st, terminate_context(writer)); reset_context(writer, RESET_GRAPH | RESET_INDENT); if (graph) { - TRY(st, write_newline(writer)); + TRY(st, write_top_level_sep(writer)); TRY(st, write_node(writer, graph, SERD_GRAPH, flags)); TRY(st, write_sep(writer, flags, SEP_GRAPH_BEGIN)); serd_node_set(&writer->context.graph, graph); @@ -1072,7 +1099,7 @@ serd_writer_write_statement(SerdWriter* const writer, } if (writer->last_sep == SEP_END_S || writer->last_sep == SEP_END_DIRECT) { - TRY(st, write_newline(writer)); + TRY(st, write_top_level_sep(writer)); } TRY(st, write_node(writer, subject, SERD_SUBJECT, flags)); @@ -1172,8 +1199,10 @@ serd_writer_finish(SerdWriter* writer) { const SerdStatus st0 = terminate_context(writer); const SerdStatus st1 = serd_byte_sink_flush(&writer->byte_sink); + free_anon_stack(writer); reset_context(writer, RESET_GRAPH | RESET_INDENT); + writer->last_sep = SEP_NONE; return st0 ? st0 : st1; } |