void DeckOutput::write( const T& value ) { if (default_count > 0) { write_sep( ); os << default_count << "*"; default_count = 0; row_count++; } write_sep( ); write_value( value ); row_count++; }
SERD_API SerdStatus serd_writer_end_anon(SerdWriter* writer, const SerdNode* node) { if (writer->syntax == SERD_NTRIPLES) { return SERD_SUCCESS; } if (serd_stack_is_empty(&writer->anon_stack) || writer->indent == 0) { w_err(writer, SERD_ERR_UNKNOWN, "unexpected end of anonymous node\n"); return SERD_ERR_UNKNOWN; } --writer->indent; write_sep(writer, SEP_ANON_END); reset_context(writer, true); writer->context = *anon_stack_top(writer); serd_stack_pop(&writer->anon_stack, sizeof(WriteContext)); const bool is_subject = serd_node_equals(node, &writer->context.subject); if (is_subject) { copy_node(&writer->context.subject, node); writer->context.predicate.type = SERD_NOTHING; } return SERD_SUCCESS; }
static void write_pred(SerdWriter* writer, SerdStatementFlags flags, const SerdNode* pred) { write_node(writer, pred, NULL, NULL, FIELD_PREDICATE, flags); write_sep(writer, SEP_P_O); copy_node(&writer->context.predicate, pred); }
static bool write_list_obj(SerdWriter* writer, SerdStatementFlags flags, const SerdNode* predicate, const SerdNode* object, const SerdNode* datatype, const SerdNode* lang) { if (!strcmp((const char*)object->buf, NS_RDF "nil")) { --writer->indent; write_sep(writer, SEP_LIST_END); return true; } else if (!strcmp((const char*)predicate->buf, NS_RDF "first")) { write_sep(writer, SEP_LIST_SEP); write_node(writer, object, datatype, lang, FIELD_OBJECT, flags); } return false; }
SERD_API SerdStatus serd_writer_write_statement(SerdWriter* writer, SerdStatementFlags flags, const SerdNode* graph, const SerdNode* subject, const SerdNode* predicate, const SerdNode* object, const SerdNode* datatype, const SerdNode* lang) { if (!subject || !predicate || !object || !subject->buf || !predicate->buf || !object->buf || !is_resource(subject) || !is_resource(predicate)) { return SERD_ERR_BAD_ARG; } #define TRY(write_result) \ if (!write_result) { \ return SERD_ERR_UNKNOWN; \ } switch (writer->syntax) { case SERD_NTRIPLES: TRY(write_node(writer, subject, NULL, NULL, FIELD_SUBJECT, flags)); sink(" ", 1, writer); TRY(write_node(writer, predicate, NULL, NULL, FIELD_PREDICATE, flags)); sink(" ", 1, writer); TRY(write_node(writer, object, datatype, lang, FIELD_OBJECT, flags)); sink(" .\n", 3, writer); return SERD_SUCCESS; default: break; } if ((flags & SERD_LIST_CONT)) { if (write_list_obj(writer, flags, predicate, object, datatype, lang)) { // Reached end of list if (--writer->list_depth == 0 && writer->list_subj.type) { reset_context(writer, true); writer->context.subject = writer->list_subj; writer->list_subj = SERD_NODE_NULL; } return SERD_SUCCESS; } } else if (serd_node_equals(subject, &writer->context.subject)) { if (serd_node_equals(predicate, &writer->context.predicate)) { // Abbreviate S P if (!(flags & SERD_ANON_O_BEGIN)) { ++writer->indent; } write_sep(writer, SEP_END_O); write_node(writer, object, datatype, lang, FIELD_OBJECT, flags); if (!(flags & SERD_ANON_O_BEGIN)) { --writer->indent; } } else { // Abbreviate S Sep sep = writer->context.predicate.type ? SEP_END_P : SEP_S_P; write_sep(writer, sep); write_pred(writer, flags, predicate); write_node(writer, object, datatype, lang, FIELD_OBJECT, flags); } } else { // No abbreviation if (writer->context.subject.type) { assert(writer->indent > 0); --writer->indent; if (serd_stack_is_empty(&writer->anon_stack)) { write_sep(writer, SEP_END_S); } } else if (!writer->empty) { write_sep(writer, SEP_S_P); } if (!(flags & SERD_ANON_CONT)) { write_node(writer, subject, NULL, NULL, FIELD_SUBJECT, flags); ++writer->indent; write_sep(writer, SEP_S_P); } else { ++writer->indent; } reset_context(writer, true); copy_node(&writer->context.subject, subject); if (!(flags & SERD_LIST_S_BEGIN)) { write_pred(writer, flags, predicate); } write_node(writer, object, datatype, lang, FIELD_OBJECT, flags); } if (flags & (SERD_ANON_S_BEGIN|SERD_ANON_O_BEGIN)) { WriteContext* ctx = (WriteContext*)serd_stack_push( &writer->anon_stack, sizeof(WriteContext)); *ctx = writer->context; WriteContext new_context = { serd_node_copy(graph), serd_node_copy(subject), SERD_NODE_NULL }; if ((flags & SERD_ANON_S_BEGIN)) { new_context.predicate = serd_node_copy(predicate); } writer->context = new_context; } else { copy_node(&writer->context.graph, graph); copy_node(&writer->context.subject, subject); copy_node(&writer->context.predicate, predicate); } return SERD_SUCCESS; }
static bool write_node(SerdWriter* writer, const SerdNode* node, const SerdNode* datatype, const SerdNode* lang, Field field, SerdStatementFlags flags) { SerdChunk uri_prefix; SerdChunk uri_suffix; bool has_scheme; switch (node->type) { case SERD_BLANK: if (writer->syntax != SERD_NTRIPLES && ((field == FIELD_SUBJECT && (flags & SERD_ANON_S_BEGIN)) || (field == FIELD_OBJECT && (flags & SERD_ANON_O_BEGIN)))) { ++writer->indent; write_sep(writer, SEP_ANON_BEGIN); } else if (writer->syntax != SERD_NTRIPLES && (field == FIELD_SUBJECT && (flags & SERD_LIST_S_BEGIN))) { assert(writer->list_depth == 0); copy_node(&writer->list_subj, node); ++writer->list_depth; ++writer->indent; write_sep(writer, SEP_LIST_BEGIN); } else if (writer->syntax != SERD_NTRIPLES && (field == FIELD_OBJECT && (flags & SERD_LIST_O_BEGIN))) { ++writer->indent; ++writer->list_depth; write_sep(writer, SEP_LIST_BEGIN); } else if (writer->syntax != SERD_NTRIPLES && ((field == FIELD_SUBJECT && (flags & SERD_EMPTY_S)) || (field == FIELD_OBJECT && (flags & SERD_EMPTY_O)))) { sink("[]", 2, writer); } else { sink("_:", 2, writer); if (writer->bprefix && !strncmp((const char*)node->buf, (const char*)writer->bprefix, writer->bprefix_len)) { sink(node->buf + writer->bprefix_len, node->n_bytes - writer->bprefix_len, writer); } else { sink(node->buf, node->n_bytes, writer); } } break; case SERD_CURIE: switch (writer->syntax) { case SERD_NTRIPLES: if (serd_env_expand(writer->env, node, &uri_prefix, &uri_suffix)) { w_err(writer, SERD_ERR_BAD_CURIE, "undefined namespace prefix `%s'\n", node->buf); return false; } sink("<", 1, writer); write_uri(writer, uri_prefix.buf, uri_prefix.len); write_uri(writer, uri_suffix.buf, uri_suffix.len); sink(">", 1, writer); break; case SERD_TURTLE: write_lname(writer, node->buf, node->n_bytes); } break; case SERD_LITERAL: if (writer->syntax == SERD_TURTLE && datatype && datatype->buf) { const char* type_uri = (const char*)datatype->buf; if (!strncmp(type_uri, NS_XSD, sizeof(NS_XSD) - 1) && ( !strcmp(type_uri + sizeof(NS_XSD) - 1, "boolean") || !strcmp(type_uri + sizeof(NS_XSD) - 1, "integer"))) { sink(node->buf, node->n_bytes, writer); break; } else if (!strcmp(type_uri + sizeof(NS_XSD) - 1, "decimal") && strchr((const char*)node->buf, '.') && node->buf[node->n_bytes - 1] != '.') { /* xsd:decimal literals without trailing digits, e.g. "5.", can not be written bare in Turtle. We could add a 0 which is prettier, but changes the text and breaks round tripping. */ sink(node->buf, node->n_bytes, writer); break; } } if (writer->syntax != SERD_NTRIPLES && (node->flags & (SERD_HAS_NEWLINE|SERD_HAS_QUOTE))) { sink("\"\"\"", 3, writer); write_text(writer, WRITE_LONG_STRING, node->buf, node->n_bytes); sink("\"\"\"", 3, writer); } else { sink("\"", 1, writer); write_text(writer, WRITE_STRING, node->buf, node->n_bytes); sink("\"", 1, writer); } if (lang && lang->buf) { sink("@", 1, writer); sink(lang->buf, lang->n_bytes, writer); } else if (datatype && datatype->buf) { sink("^^", 2, writer); write_node(writer, datatype, NULL, NULL, FIELD_NONE, flags); } break; case SERD_URI: has_scheme = serd_uri_string_has_scheme(node->buf); if (field == FIELD_PREDICATE && (writer->syntax == SERD_TURTLE) && !strcmp((const char*)node->buf, NS_RDF "type")) { sink("a", 1, writer); break; } else if ((writer->syntax == SERD_TURTLE) && !strcmp((const char*)node->buf, NS_RDF "nil")) { sink("()", 2, writer); break; } else if (has_scheme && (writer->style & SERD_STYLE_CURIED)) { SerdNode prefix; SerdChunk suffix; if (serd_env_qualify(writer->env, node, &prefix, &suffix)) { write_uri(writer, prefix.buf, prefix.n_bytes); sink(":", 1, writer); write_uri(writer, suffix.buf, suffix.len); break; } } sink("<", 1, writer); if (writer->style & SERD_STYLE_RESOLVED) { SerdURI in_base_uri, uri, abs_uri; serd_env_get_base_uri(writer->env, &in_base_uri); serd_uri_parse(node->buf, &uri); serd_uri_resolve(&uri, &in_base_uri, &abs_uri); bool rooted = uri_is_under(&writer->base_uri, &writer->root_uri); SerdURI* root = rooted ? &writer->root_uri : & writer->base_uri; if (!uri_is_under(&abs_uri, root) || writer->syntax == SERD_NTRIPLES) { serd_uri_serialise(&abs_uri, uri_sink, writer); } else { serd_uri_serialise_relative( &uri, &writer->base_uri, root, uri_sink, writer); } } else { write_uri(writer, node->buf, node->n_bytes); } sink(">", 1, writer); default: break; } writer->last_sep = SEP_NONE; return true; }