void AtomWriter::forge_uri(const Raul::URI& uri) { if (serd_uri_string_has_scheme((const uint8_t*)uri.c_str())) { lv2_atom_forge_urid(&_forge, _map.map_uri(uri.c_str())); } else { lv2_atom_forge_uri(&_forge, uri.c_str(), uri.length()); } }
static SordNode* sord_new_uri_counted(SordWorld* world, const uint8_t* str, size_t n_bytes, size_t n_chars, bool copy) { if (!serd_uri_string_has_scheme(str)) { error(world, SERD_ERR_BAD_ARG, "attempt to map invalid URI `%s'\n", str); return NULL; // Can't intern relative URIs } const SordNode key = { { str, n_bytes, n_chars, 0, SERD_URI }, 1, { { 0 } } }; return sord_insert_node(world, &key, copy); }
SordNode* sord_new_relative_uri(SordWorld* world, const uint8_t* str, const uint8_t* base_str) { if (serd_uri_string_has_scheme(str)) { return sord_new_uri(world, str); } SerdURI buri = SERD_URI_NULL; SerdNode base = serd_node_new_uri_from_string(base_str, NULL, &buri); SerdNode node = serd_node_new_uri_from_string(str, &buri, NULL); SordNode* ret = sord_new_uri_counted( world, node.buf, node.n_bytes, node.n_chars, false); serd_node_free(&base); return ret; }
SERD_API const uint8_t* serd_uri_to_path(const uint8_t* uri) { const uint8_t* path = uri; if (!is_windows_path(uri) && serd_uri_string_has_scheme(uri)) { if (strncmp((const char*)uri, "file:", 5)) { fprintf(stderr, "Non-file URI `%s'\n", uri); return NULL; } else if (!strncmp((const char*)uri, "file://localhost/", 17)) { path = uri + 16; } else if (!strncmp((const char*)uri, "file://", 7)) { path = uri + 7; } else { fprintf(stderr, "Invalid file URI `%s'\n", uri); return NULL; } if (is_windows_path(path + 1)) { ++path; // Special case for terrible Windows file URIs } } return path; }
SERD_API SerdStatus serd_env_set_prefix(SerdEnv* env, const SerdNode* name, const SerdNode* uri_node) { if (!name->buf || uri_node->type != SERD_URI) { return SERD_ERR_BAD_ARG; } else if (serd_uri_string_has_scheme(uri_node->buf)) { // Set prefix to absolute URI serd_env_add(env, name, uri_node); } else { // Resolve relative URI and create a new node and URI for it SerdURI abs_uri; SerdNode abs_uri_node = serd_node_new_uri_from_node( uri_node, &env->base_uri, &abs_uri); // Set prefix to resolved (absolute) URI serd_env_add(env, name, &abs_uri_node); serd_node_free(&abs_uri_node); } return SERD_SUCCESS; }
SordNode* sord_node_from_serd_node(SordWorld* world, SerdEnv* env, const SerdNode* sn, const SerdNode* datatype, const SerdNode* lang) { if (!sn) { return NULL; } SordNode* datatype_node = NULL; SordNode* ret = NULL; switch (sn->type) { case SERD_NOTHING: return NULL; case SERD_LITERAL: datatype_node = sord_node_from_serd_node( world, env, datatype, NULL, NULL), ret = sord_new_literal_counted( world, datatype_node, sn->buf, sn->n_bytes, sn->n_chars, sn->flags, lang ? (const char*)lang->buf : NULL); sord_node_free(world, datatype_node); return ret; case SERD_URI: if (serd_uri_string_has_scheme(sn->buf)) { return sord_new_uri_counted( world, sn->buf, sn->n_bytes, sn->n_chars, true); } else { SerdURI base_uri; serd_env_get_base_uri(env, &base_uri); SerdURI abs_uri; SerdNode abs_uri_node = serd_node_new_uri_from_node( sn, &base_uri, &abs_uri); ret = sord_new_uri_counted(world, abs_uri_node.buf, abs_uri_node.n_bytes, abs_uri_node.n_chars, true); serd_node_free(&abs_uri_node); return ret; } case SERD_CURIE: { SerdChunk uri_prefix; SerdChunk uri_suffix; if (serd_env_expand(env, sn, &uri_prefix, &uri_suffix)) { error(world, SERD_ERR_BAD_CURIE, "failed to expand CURIE `%s'\n", sn->buf); return NULL; } const size_t uri_len = uri_prefix.len + uri_suffix.len; uint8_t* buf = (uint8_t*)malloc(uri_len + 1); memcpy(buf, uri_prefix.buf, uri_prefix.len); memcpy(buf + uri_prefix.len, uri_suffix.buf, uri_suffix.len); buf[uri_len] = '\0'; ret = sord_new_uri_counted( world, buf, uri_prefix.len + uri_suffix.len, uri_prefix.len + uri_suffix.len, false); // FIXME: UTF-8 return ret; } case SERD_BLANK: return sord_new_blank_counted(world, sn->buf, sn->n_bytes, sn->n_chars); } return NULL; }
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; }
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; switch (node->type) { case SERD_NOTHING: return false; 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; serd_writer_write_delim(writer, '['); } else if (writer->syntax != SERD_NTRIPLES && ((field == FIELD_SUBJECT && (flags & SERD_EMPTY_S)) || (field == FIELD_OBJECT && (flags & SERD_EMPTY_O)))) { writer->sink("[]", 2, writer->stream); } else { writer->sink("_:", 2, writer->stream); if (writer->bprefix && !strncmp((const char*)node->buf, (const char*)writer->bprefix, writer->bprefix_len)) { writer->sink(node->buf + writer->bprefix_len, node->n_bytes - writer->bprefix_len, writer->stream); } else { writer->sink(node->buf, node->n_bytes, writer->stream); } } break; case SERD_CURIE: switch (writer->syntax) { case SERD_NTRIPLES: if (serd_env_expand(writer->env, node, &uri_prefix, &uri_suffix)) { fprintf(stderr, "Undefined namespace prefix `%s'\n", node->buf); return false; } writer->sink("<", 1, writer->stream); write_text(writer, WRITE_URI, uri_prefix.buf, uri_prefix.len, '>'); write_text(writer, WRITE_URI, uri_suffix.buf, uri_suffix.len, '>'); writer->sink(">", 1, writer->stream); break; case SERD_TURTLE: writer->sink(node->buf, node->n_bytes, writer->stream); } break; case SERD_LITERAL: if (writer->syntax == SERD_TURTLE && datatype && datatype->buf) { // TODO: compare against NS_XSD prefix once if (!strcmp((const char*)datatype->buf, NS_XSD "boolean") || !strcmp((const char*)datatype->buf, NS_XSD "decimal") || !strcmp((const char*)datatype->buf, NS_XSD "integer")) { writer->sink(node->buf, node->n_bytes, writer->stream); break; } } if (writer->syntax != SERD_NTRIPLES && ((node->flags & SERD_HAS_NEWLINE) || (node->flags & SERD_HAS_QUOTE))) { writer->sink("\"\"\"", 3, writer->stream); write_text(writer, WRITE_LONG_STRING, node->buf, node->n_bytes, '\0'); writer->sink("\"\"\"", 3, writer->stream); } else { writer->sink("\"", 1, writer->stream); write_text(writer, WRITE_STRING, node->buf, node->n_bytes, '"'); writer->sink("\"", 1, writer->stream); } if (lang && lang->buf) { writer->sink("@", 1, writer->stream); writer->sink(lang->buf, lang->n_bytes, writer->stream); } else if (datatype && datatype->buf) { writer->sink("^^", 2, writer->stream); write_node(writer, datatype, NULL, NULL, FIELD_NONE, flags); } break; case SERD_URI: if ((writer->syntax == SERD_TURTLE) && !strcmp((const char*)node->buf, NS_RDF "type")) { writer->sink("a", 1, writer->stream); return true; } else if ((writer->style & SERD_STYLE_CURIED) && serd_uri_string_has_scheme(node->buf)) { SerdNode prefix; SerdChunk suffix; if (serd_env_qualify(writer->env, node, &prefix, &suffix)) { write_text(writer, WRITE_URI, prefix.buf, prefix.n_bytes, '>'); writer->sink(":", 1, writer->stream); write_text(writer, WRITE_URI, suffix.buf, suffix.len, '>'); return true; } } else if ((writer->style & SERD_STYLE_RESOLVED) && !serd_uri_string_has_scheme(node->buf)) { SerdURI uri; if (!serd_uri_parse(node->buf, &uri)) { SerdURI abs_uri; serd_uri_resolve(&uri, &writer->base_uri, &abs_uri); writer->sink("<", 1, writer->stream); serd_uri_serialise(&abs_uri, writer->sink, writer->stream); writer->sink(">", 1, writer->stream); return true; } } writer->sink("<", 1, writer->stream); write_text(writer, WRITE_URI, node->buf, node->n_bytes, '>'); writer->sink(">", 1, writer->stream); return true; } return true; }