cannam@226: /* cannam@226: Copyright 2011-2015 David Robillard cannam@226: cannam@226: Permission to use, copy, modify, and/or distribute this software for any cannam@226: purpose with or without fee is hereby granted, provided that the above cannam@226: copyright notice and this permission notice appear in all copies. cannam@226: cannam@226: THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES cannam@226: WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF cannam@226: MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR cannam@226: ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES cannam@226: WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN cannam@226: ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF cannam@226: OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. cannam@226: */ cannam@226: cannam@226: #include cannam@226: #include cannam@226: #include cannam@226: cannam@226: #include "serd/serd.h" cannam@226: cannam@226: #include "sord_config.h" cannam@226: #include "sord_internal.h" cannam@226: cannam@226: struct SordInserterImpl { cannam@226: SordModel* model; cannam@226: SerdEnv* env; cannam@226: }; cannam@226: cannam@226: SordInserter* cannam@226: sord_inserter_new(SordModel* model, cannam@226: SerdEnv* env) cannam@226: { cannam@226: SordInserter* inserter = (SordInserter*)malloc(sizeof(SordInserter)); cannam@226: inserter->model = model; cannam@226: inserter->env = env; cannam@226: return inserter; cannam@226: } cannam@226: cannam@226: void cannam@226: sord_inserter_free(SordInserter* inserter) cannam@226: { cannam@226: free(inserter); cannam@226: } cannam@226: cannam@226: SerdStatus cannam@226: sord_inserter_set_base_uri(SordInserter* inserter, cannam@226: const SerdNode* uri_node) cannam@226: { cannam@226: return serd_env_set_base_uri(inserter->env, uri_node); cannam@226: } cannam@226: cannam@226: SerdStatus cannam@226: sord_inserter_set_prefix(SordInserter* inserter, cannam@226: const SerdNode* name, cannam@226: const SerdNode* uri_node) cannam@226: { cannam@226: return serd_env_set_prefix(inserter->env, name, uri_node); cannam@226: } cannam@226: cannam@226: SerdStatus cannam@226: sord_inserter_write_statement(SordInserter* inserter, cannam@226: SerdStatementFlags flags, cannam@226: const SerdNode* graph, cannam@226: const SerdNode* subject, cannam@226: const SerdNode* predicate, cannam@226: const SerdNode* object, cannam@226: const SerdNode* object_datatype, cannam@226: const SerdNode* object_lang) cannam@226: { cannam@226: SordWorld* world = sord_get_world(inserter->model); cannam@226: SerdEnv* env = inserter->env; cannam@226: cannam@226: SordNode* g = sord_node_from_serd_node(world, env, graph, NULL, NULL); cannam@226: SordNode* s = sord_node_from_serd_node(world, env, subject, NULL, NULL); cannam@226: SordNode* p = sord_node_from_serd_node(world, env, predicate, NULL, NULL); cannam@226: SordNode* o = sord_node_from_serd_node(world, env, object, cannam@226: object_datatype, object_lang); cannam@226: cannam@226: if (!s || !p || !o) { cannam@226: return SERD_ERR_BAD_ARG; cannam@226: } cannam@226: cannam@226: const SordQuad tup = { s, p, o, g }; cannam@226: sord_add(inserter->model, tup); cannam@226: cannam@226: sord_node_free(world, o); cannam@226: sord_node_free(world, p); cannam@226: sord_node_free(world, s); cannam@226: sord_node_free(world, g); cannam@226: cannam@226: return SERD_SUCCESS; cannam@226: } cannam@226: cannam@226: SORD_API cannam@226: SerdReader* cannam@226: sord_new_reader(SordModel* model, cannam@226: SerdEnv* env, cannam@226: SerdSyntax syntax, cannam@226: SordNode* graph) cannam@226: { cannam@226: SordInserter* inserter = sord_inserter_new(model, env); cannam@226: cannam@226: SerdReader* reader = serd_reader_new( cannam@226: syntax, inserter, (void (*)(void*))sord_inserter_free, cannam@226: (SerdBaseSink)sord_inserter_set_base_uri, cannam@226: (SerdPrefixSink)sord_inserter_set_prefix, cannam@226: (SerdStatementSink)sord_inserter_write_statement, cannam@226: NULL); cannam@226: cannam@226: if (graph) { cannam@226: serd_reader_set_default_graph(reader, sord_node_to_serd_node(graph)); cannam@226: } cannam@226: cannam@226: return reader; cannam@226: } cannam@226: cannam@226: static SerdStatus cannam@226: write_statement(SordModel* sord, cannam@226: SerdWriter* writer, cannam@226: SordQuad tup, cannam@226: SerdStatementFlags flags) cannam@226: { cannam@226: const SordNode* s = tup[SORD_SUBJECT]; cannam@226: const SordNode* p = tup[SORD_PREDICATE]; cannam@226: const SordNode* o = tup[SORD_OBJECT]; cannam@226: const SordNode* d = sord_node_get_datatype(o); cannam@226: const SerdNode* ss = sord_node_to_serd_node(s); cannam@226: const SerdNode* sp = sord_node_to_serd_node(p); cannam@226: const SerdNode* so = sord_node_to_serd_node(o); cannam@226: const SerdNode* sd = sord_node_to_serd_node(d); cannam@226: cannam@226: const char* lang_str = sord_node_get_language(o); cannam@226: size_t lang_len = lang_str ? strlen(lang_str) : 0; cannam@226: SerdNode language = SERD_NODE_NULL; cannam@226: if (lang_str) { cannam@226: language.type = SERD_LITERAL; cannam@226: language.n_bytes = lang_len; cannam@226: language.n_chars = lang_len; cannam@226: language.buf = (const uint8_t*)lang_str; cannam@226: }; cannam@226: cannam@226: // TODO: Subject abbreviation cannam@226: cannam@226: if (sord_node_is_inline_object(s) && !(flags & SERD_ANON_CONT)) { cannam@226: return SERD_SUCCESS; cannam@226: } cannam@226: cannam@226: SerdStatus st = SERD_SUCCESS; cannam@226: if (sord_node_is_inline_object(o)) { cannam@226: SordQuad sub_pat = { o, 0, 0, 0 }; cannam@226: SordIter* sub_iter = sord_find(sord, sub_pat); cannam@226: cannam@226: SerdStatementFlags start_flags = flags cannam@226: | ((sub_iter) ? SERD_ANON_O_BEGIN : SERD_EMPTY_O); cannam@226: cannam@226: st = serd_writer_write_statement( cannam@226: writer, start_flags, NULL, ss, sp, so, sd, &language); cannam@226: cannam@226: if (!st && sub_iter) { cannam@226: flags |= SERD_ANON_CONT; cannam@226: for (; !st && !sord_iter_end(sub_iter); sord_iter_next(sub_iter)) { cannam@226: SordQuad sub_tup; cannam@226: sord_iter_get(sub_iter, sub_tup); cannam@226: st = write_statement(sord, writer, sub_tup, flags); cannam@226: } cannam@226: sord_iter_free(sub_iter); cannam@226: serd_writer_end_anon(writer, so); cannam@226: } cannam@226: } else { cannam@226: st = serd_writer_write_statement( cannam@226: writer, flags, NULL, ss, sp, so, sd, &language); cannam@226: } cannam@226: cannam@226: return st; cannam@226: } cannam@226: cannam@226: bool cannam@226: sord_write(SordModel* model, cannam@226: SerdWriter* writer, cannam@226: SordNode* graph) cannam@226: { cannam@226: SordQuad pat = { 0, 0, 0, graph }; cannam@226: SordIter* iter = sord_find(model, pat); cannam@226: return sord_write_iter(iter, writer); cannam@226: } cannam@226: cannam@226: bool cannam@226: sord_write_iter(SordIter* iter, cannam@226: SerdWriter* writer) cannam@226: { cannam@226: if (!iter) { cannam@226: return false; cannam@226: } cannam@226: cannam@226: SordModel* model = (SordModel*)sord_iter_get_model(iter); cannam@226: SerdStatus st = SERD_SUCCESS; cannam@226: for (; !st && !sord_iter_end(iter); sord_iter_next(iter)) { cannam@226: SordQuad tup; cannam@226: sord_iter_get(iter, tup); cannam@226: st = write_statement(model, writer, tup, 0); cannam@226: } cannam@226: sord_iter_free(iter); cannam@226: cannam@226: return !st; cannam@226: }