aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2021-01-13 20:22:49 +0100
committerDavid Robillard <d@drobilla.net>2022-01-13 23:04:09 -0500
commitd8e718453cf7a29045b648683b0645094bc66ae9 (patch)
treec3e0776fddbcb60caa90fbd984a3710365cdf8de /src
parentd30f90cae709a9192aa29f219a494c62b865e0f8 (diff)
downloadserd-d8e718453cf7a29045b648683b0645094bc66ae9.tar.gz
serd-d8e718453cf7a29045b648683b0645094bc66ae9.tar.bz2
serd-d8e718453cf7a29045b648683b0645094bc66ae9.zip
Add support for writing terse collections
Diffstat (limited to 'src')
-rw-r--r--src/writer.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/src/writer.c b/src/writer.c
index e0db3a06..8c96b2a8 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -61,8 +61,11 @@ typedef enum {
SEP_ANON_S_P, ///< Between start of anonymous node and predicate
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;
@@ -88,12 +91,15 @@ static const SepRule rules[] = {
{",", 1, +0, SEP_ALL, SEP_NONE, ~(M(SEP_ANON_END) | M(SEP_LIST_END))},
{"", 0, +1, SEP_NONE, SEP_NONE, SEP_ALL},
{" ", 1, +0, SEP_NONE, SEP_NONE, SEP_NONE},
- {"[", 1, +1, M(SEP_END_O), SEP_NONE, SEP_NONE},
+ {"[", 1, +1, M(SEP_END_O), M(SEP_TLIST_BEGIN) | M(SEP_TLIST_SEP), SEP_NONE},
{"", 0, +0, SEP_NONE, SEP_ALL, SEP_NONE},
{"]", 1, -1, SEP_NONE, ~M(SEP_ANON_BEGIN), SEP_NONE},
{"(", 1, +1, M(SEP_END_O), SEP_NONE, SEP_ALL},
{"", 0, +0, SEP_NONE, SEP_ALL, SEP_NONE},
{")", 1, -1, SEP_NONE, SEP_ALL, SEP_NONE},
+ {"(", 1, +1, SEP_NONE, SEP_NONE, SEP_NONE},
+ {"", 0, +0, SEP_ALL, SEP_NONE, SEP_NONE},
+ {")", 1, -1, SEP_NONE, SEP_NONE, SEP_NONE},
{"{", 1, +1, SEP_ALL, SEP_NONE, SEP_NONE},
{"}", 1, -1, SEP_NONE, SEP_NONE, SEP_ALL},
};
@@ -483,9 +489,9 @@ uri_sink(const void* buf, size_t size, size_t nmemb, void* stream)
}
static void
-write_newline(SerdWriter* writer)
+write_newline(SerdWriter* writer, bool terse)
{
- if (writer->flags & SERD_WRITE_TERSE) {
+ if (terse || (writer->flags & SERD_WRITE_TERSE)) {
sink(" ", 1, writer);
} else {
sink("\n", 1, writer);
@@ -499,16 +505,21 @@ static void
write_top_level_sep(SerdWriter* writer)
{
if (!writer->empty && !(writer->flags & SERD_WRITE_TERSE)) {
- write_newline(writer);
+ write_newline(writer, false);
}
}
static bool
write_sep(SerdWriter* writer, const SerdStatementFlags flags, Sep sep)
{
- (void)flags;
+ const SepRule* const rule = &rules[sep];
- const SepRule* rule = &rules[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->pre_line_after & (1u << writer->last_sep)) ||
@@ -520,7 +531,7 @@ write_sep(SerdWriter* writer, const SerdStatementFlags flags, Sep sep)
// Write newline or space before separator if necessary
if (rule->pre_line_after & (1u << writer->last_sep)) {
- write_newline(writer);
+ write_newline(writer, terse);
} else if (rule->pre_space_after & (1u << writer->last_sep)) {
sink(" ", 1, writer);
}
@@ -530,7 +541,7 @@ write_sep(SerdWriter* writer, const SerdStatementFlags flags, Sep sep)
// Write newline after separator if necessary
if (rule->post_line_after & (1u << writer->last_sep)) {
- write_newline(writer);
+ write_newline(writer, terse);
writer->last_sep = SEP_NONE;
} else {
writer->last_sep = sep;
@@ -844,8 +855,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_ERR_BAD_ARG;
}