aboutsummaryrefslogtreecommitdiffstats
path: root/src/writer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/writer.c')
-rw-r--r--src/writer.c57
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;
}