aboutsummaryrefslogtreecommitdiffstats
path: root/src/writer.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-03-10 22:50:31 +0100
committerDavid Robillard <d@drobilla.net>2019-12-20 10:26:55 -0500
commit0474b622e7fb5b58268bd7064f054a75d1e3a550 (patch)
tree81f3a335e979818f5b32c656ef9955ab4103883b /src/writer.c
parent56d89f80566dbcf4089d1b08a0361aaef97de380 (diff)
downloadserd-0474b622e7fb5b58268bd7064f054a75d1e3a550.tar.gz
serd-0474b622e7fb5b58268bd7064f054a75d1e3a550.tar.bz2
serd-0474b622e7fb5b58268bd7064f054a75d1e3a550.zip
Add support for writing terse collections
Diffstat (limited to 'src/writer.c')
-rw-r--r--src/writer.c35
1 files changed, 23 insertions, 12 deletions
diff --git a/src/writer.c b/src/writer.c
index 15b527a2..037454eb 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;
@@ -89,12 +92,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},
{"<", 1, +0, SEP_NONE, SEP_NONE, SEP_NONE},
@@ -378,9 +384,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);
@@ -394,16 +400,19 @@ 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* 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
writer->indent =
@@ -413,7 +422,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);
}
@@ -423,7 +432,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;
@@ -758,8 +767,10 @@ serd_writer_write_statement(SerdWriter* writer,
const SerdNode* const graph = serd_statement_get_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;
}