From 98ea88b5fd404ff4ba43709f731ba074f291eb5b Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 19 Apr 2007 16:49:25 +0000 Subject: Added Redland dependency, using in-memory RDF models. Numerous significant performance improvements. git-svn-id: http://svn.drobilla.net/lad/slv2@457 a436a847-0d15-0410-975c-d299462d15a1 --- src/Makefile.am | 12 +-- src/library.c | 44 ---------- src/plugin.c | 242 +++++++++++++++++++++++++++++++++++++++++---------- src/plugininstance.c | 27 +++--- src/pluginlist.c | 102 ++++++++++++---------- src/port.c | 167 +++++++++++++++++------------------ src/private_types.h | 52 +++++++---- src/query.c | 164 ++++++++++++++++------------------ 8 files changed, 466 insertions(+), 344 deletions(-) delete mode 100644 src/library.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index b28b75d..eb25597 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,16 +1,16 @@ -AM_CFLAGS = -std=c99 -I$(top_srcdir)/include -I$(top_srcdir) @RASQAL_CFLAGS@ -DLIBSLV2_SOURCE -DLV2_TTL_PATH=\"@lv2ttlpath@\" +AM_CFLAGS = -std=c99 -I$(top_srcdir)/include -I$(top_srcdir) @REDLAND_CFLAGS@ -DLIBSLV2_SOURCE -DLV2_TTL_PATH=\"@lv2ttlpath@\" AM_LDFLAGS = `pkg-config --libs rasqal` lib_LTLIBRARIES = libslv2.la -libslv2_la_LIBADD = @RASQAL_LIBS@ +libslv2_la_LIBADD = @REDLAND_LIBS@ libslv2_la_SOURCES = \ private_types.h \ + model.c \ plugin.c \ query.c \ port.c \ pluginlist.c \ - util.c \ - plugininstance.c \ - library.c \ - stringlist.c + plugininstance.c \ + stringlist.c \ + util.c diff --git a/src/library.c b/src/library.c deleted file mode 100644 index 4ad97c3..0000000 --- a/src/library.c +++ /dev/null @@ -1,44 +0,0 @@ -/* SLV2 - * Copyright (C) 2007 Dave Robillard - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include -#include - -raptor_uri* slv2_ontology_uri = NULL; - - -void -slv2_init() -{ - rasqal_init(); - - slv2_ontology_uri = raptor_new_uri((const unsigned char*) - "file://" LV2_TTL_PATH); -} - - -void -slv2_finish() -{ - raptor_free_uri(slv2_ontology_uri); - slv2_ontology_uri = NULL; - - rasqal_finish(); -} - diff --git a/src/plugin.c b/src/plugin.c index abb577b..ab36caf 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -29,8 +29,54 @@ #include "private_types.h" +/* private */ +SLV2Plugin +slv2_plugin_new(SLV2Model model, librdf_uri* uri, const char* binary_uri) +{ + struct _Plugin* plugin = malloc(sizeof(struct _Plugin)); + plugin->model = model; + plugin->plugin_uri = librdf_new_uri_from_uri(uri); + plugin->binary_uri = strdup(binary_uri); + plugin->data_uris = raptor_new_sequence((void (*)(void*))&raptor_free_uri, NULL); + plugin->ports = raptor_new_sequence((void (*)(void*))&slv2_port_free, NULL); + plugin->storage = NULL; + plugin->rdf = NULL; + + return plugin; +} + + +/* private */ +void +slv2_plugin_free(SLV2Plugin p) +{ + librdf_free_uri(p->plugin_uri); + p->plugin_uri = NULL; + + //free(p->bundle_url); + free(p->binary_uri); + + raptor_free_sequence(p->ports); + p->ports = NULL; + + if (p->rdf) { + librdf_free_model(p->rdf); + p->rdf = NULL; + } + + if (p->storage) { + librdf_free_storage(p->storage); + p->storage = NULL; + } + + raptor_free_sequence(p->data_uris); + + free(p); +} + + // FIXME: ew -rasqal_query_results* +librdf_query_results* slv2_plugin_query(SLV2Plugin plugin, const char* sparql_str); @@ -38,42 +84,127 @@ slv2_plugin_query(SLV2Plugin plugin, SLV2Plugin slv2_plugin_duplicate(SLV2Plugin p) { + fprintf(stderr, "FIXME: duplicate\n"); + assert(p); struct _Plugin* result = malloc(sizeof(struct _Plugin)); - result->plugin_uri = strdup(p->plugin_uri); - result->bundle_url = strdup(p->bundle_url); - result->lib_uri = strdup(p->lib_uri); + result->model = p->model; + result->plugin_uri = librdf_new_uri_from_uri(p->plugin_uri); + + //result->bundle_url = strdup(p->bundle_url); + result->binary_uri = strdup(p->binary_uri); result->data_uris = slv2_strings_new(); for (unsigned i=0; i < slv2_strings_size(p->data_uris); ++i) raptor_sequence_push(result->data_uris, strdup(slv2_strings_get_at(p->data_uris, i))); + + result->ports = raptor_new_sequence((void (*)(void*))&slv2_port_free, NULL); + for (int i=0; i < raptor_sequence_size(p->ports); ++i) + raptor_sequence_push(result->ports, slv2_port_duplicate(raptor_sequence_get_at(p->ports, i))); + + result->ports = NULL; + result->storage = NULL; + result->rdf = NULL; + return result; } +/** comparator for sorting */ +int +slv2_port_compare_by_index(const void* a, const void* b) +{ + SLV2Port port_a = *(SLV2Port*)a; + SLV2Port port_b = *(SLV2Port*)b; + + if (port_a->index < port_b->index) + return -1; + else if (port_a->index == port_b->index) + return 0; + else //if (port_a->index > port_b->index) + return 1; +} + + void -slv2_plugin_free(SLV2Plugin p) +slv2_plugin_load(SLV2Plugin p) { - free(p->plugin_uri); - free(p->bundle_url); - free(p->lib_uri); - slv2_strings_free(p->data_uris); - free(p); + //printf("Loading cache for %s\n", (const char*)librdf_uri_as_string(p->plugin_uri)); + + if (!p->storage) { + assert(!p->rdf); + p->storage = librdf_new_storage(p->model->world, "hashes", NULL, + "hash-type='memory'"); + p->rdf = librdf_new_model(p->model->world, p->storage, NULL); + } + + // Parse all the plugin's data files into RDF model + for (int i=0; i < raptor_sequence_size(p->data_uris); ++i) { + librdf_uri* data_uri = raptor_sequence_get_at(p->data_uris, i); + librdf_parser_parse_into_model(p->model->parser, data_uri, NULL, p->rdf); + } + + // Load ports + const unsigned char* query = (const unsigned char*) + "PREFIX : \n" + "SELECT DISTINCT ?port ?symbol ?index WHERE {\n" + "<> :port ?port .\n" + "?port :symbol ?symbol ;\n" + " :index ?index .\n" + "}"; + + librdf_query* q = librdf_new_query(p->model->world, "sparql", + NULL, query, p->plugin_uri); + + librdf_query_results* results = librdf_query_execute(q, p->rdf); + + while (!librdf_query_results_finished(results)) { + + //librdf_node* port_node = librdf_query_results_get_binding_value(results, 0); + librdf_node* symbol_node = librdf_query_results_get_binding_value(results, 1); + librdf_node* index_node = librdf_query_results_get_binding_value(results, 2); + + //assert(librdf_node_is_blank(port_node)); + assert(librdf_node_is_literal(symbol_node)); + assert(librdf_node_is_literal(index_node)); + + //const char* id = (const char*)librdf_node_get_blank_identifier(port_node); + const char* symbol = (const char*)librdf_node_get_literal_value(symbol_node); + const char* index = (const char*)librdf_node_get_literal_value(index_node); + + //printf("%s: PORT: %s %s\n", p->plugin_uri, index, symbol); + + // Create a new SLV2Port + SLV2Port port = slv2_port_new((unsigned)atoi(index), symbol); + raptor_sequence_push(p->ports, port); + + librdf_free_node(symbol_node); + librdf_free_node(index_node); + + librdf_query_results_next(results); + } + + raptor_sequence_sort(p->ports, slv2_port_compare_by_index); + + if (results) + librdf_free_query_results(results); + + librdf_free_query(q); + + //printf("%p %s: NUM PORTS: %d\n", (void*)p, p->plugin_uri, slv2_plugin_get_num_ports(p)); } const char* slv2_plugin_get_uri(SLV2Plugin p) { - assert(p); - return p->plugin_uri; + return (const char*)librdf_uri_as_string(p->plugin_uri); } SLV2Strings slv2_plugin_get_data_uris(SLV2Plugin p) { - assert(p); return p->data_uris; } @@ -81,8 +212,7 @@ slv2_plugin_get_data_uris(SLV2Plugin p) const char* slv2_plugin_get_library_uri(SLV2Plugin p) { - assert(p); - return p->lib_uri; + return p->binary_uri; } @@ -91,42 +221,47 @@ slv2_plugin_verify(SLV2Plugin plugin) { char* query_str = "SELECT DISTINCT ?type ?name ?license ?port WHERE {\n" - "plugin: a ?type ;\n" + "<> a ?type ;\n" "doap:name ?name ;\n" "doap:license ?license ;\n" "lv2:port [ lv2:index ?port ] .\n}"; - rasqal_query_results* results = slv2_plugin_query(plugin, query_str); + librdf_query_results* results = slv2_plugin_query(plugin, query_str); bool has_type = false; bool has_name = false; bool has_license = false; bool has_port = false; - while (!rasqal_query_results_finished(results)) { - rasqal_literal* literal = rasqal_query_results_get_binding_value(results, 0); - const char* const type = (const char*)rasqal_literal_as_string(literal); - literal = rasqal_query_results_get_binding_value(results, 1); - const char* const name = (const char*)rasqal_literal_as_string(literal); - rasqal_literal* license = rasqal_query_results_get_binding_value(results, 2); - rasqal_literal* port = rasqal_query_results_get_binding_value(results, 3); + while (!librdf_query_results_finished(results)) { + librdf_node* type_node = librdf_query_results_get_binding_value(results, 0); + const char* const type_str = (const char*)librdf_node_get_literal_value(type_node); + librdf_node* name_node = librdf_query_results_get_binding_value(results, 1); + //const char* const name = (const char*)librdf_node_get_literal_value(name_node); + librdf_node* license_node = librdf_query_results_get_binding_value(results, 2); + librdf_node* port_node = librdf_query_results_get_binding_value(results, 3); - if (!strcmp(type, "http://lv2plug.in/ontology#Plugin")) + if (!strcmp(type_str, "http://lv2plug.in/ontology#Plugin")) has_type = true; - if (name) + if (name_node) has_name = true; - if (license) + if (license_node) has_license = true; - if (port) + if (port_node) has_port = true; - rasqal_query_results_next(results); + librdf_free_node(type_node); + librdf_free_node(name_node); + librdf_free_node(license_node); + librdf_free_node(port_node); + + librdf_query_results_next(results); } - rasqal_free_query_results(results); + librdf_free_query_results(results); if ( ! (has_type && has_name && has_license && has_port) ) { fprintf(stderr, "Invalid LV2 Plugin %s\n", slv2_plugin_get_uri(plugin)); @@ -161,8 +296,8 @@ slv2_plugin_get_value(SLV2Plugin p, assert(predicate); char* query = slv2_strjoin( - "SELECT DISTINCT ?value WHERE {\n" - "plugin: ", predicate, " ?value .\n" + "SELECT DISTINCT ?value WHERE {" + "<> ", predicate, " ?value .\n" "}\n", NULL); SLV2Strings result = slv2_plugin_simple_query(p, query, "value"); @@ -210,11 +345,7 @@ slv2_plugin_get_hints(SLV2Plugin p) uint32_t slv2_plugin_get_num_ports(SLV2Plugin p) { - const char* const query = - "SELECT DISTINCT ?port\n" - "WHERE { plugin: lv2:port ?port }\n"; - - return (uint32_t)slv2_plugin_query_count(p, query); + return raptor_sequence_size(p->ports); } @@ -223,7 +354,7 @@ slv2_plugin_has_latency(SLV2Plugin p) { const char* const query = "SELECT DISTINCT ?port WHERE {\n" - " plugin: lv2:port ?port .\n" + " <> lv2:port ?port .\n" " ?port lv2:portHint lv2:reportsLatency .\n" "}\n"; @@ -242,7 +373,7 @@ slv2_plugin_get_latency_port(SLV2Plugin p) { const char* const query = "SELECT DISTINCT ?value WHERE {\n" - " plugin: lv2:port ?port .\n" + " <> lv2:port ?port .\n" " ?port lv2:portHint lv2:reportsLatency ;\n" " lv2:index ?index .\n" "}\n"; @@ -264,9 +395,9 @@ slv2_plugin_get_supported_features(SLV2Plugin p) { const char* const query = "SELECT DISTINCT ?feature WHERE {\n" - " { plugin: lv2:optionalHostFeature ?feature }\n" + " { <> lv2:optionalHostFeature ?feature }\n" " UNION\n" - " { plugin: lv2:requiredHostFeature ?feature }\n" + " { <> lv2:requiredHostFeature ?feature }\n" "}\n"; SLV2Strings result = slv2_plugin_simple_query(p, query, "feature"); @@ -280,7 +411,7 @@ slv2_plugin_get_optional_features(SLV2Plugin p) { const char* const query = "SELECT DISTINCT ?feature WHERE {\n" - " plugin: lv2:optionalHostFeature ?feature .\n" + " <> lv2:optionalHostFeature ?feature .\n" "}\n"; SLV2Strings result = slv2_plugin_simple_query(p, query, "feature"); @@ -294,7 +425,7 @@ slv2_plugin_get_required_features(SLV2Plugin p) { const char* const query = "SELECT DISTINCT ?feature WHERE {\n" - " plugin: lv2:requiredHostFeature ?feature .\n" + " <> lv2:requiredHostFeature ?feature .\n" "}\n"; SLV2Strings result = slv2_plugin_simple_query(p, query, "feature"); @@ -302,3 +433,26 @@ slv2_plugin_get_required_features(SLV2Plugin p) return result; } + +SLV2Port +slv2_plugin_get_port_by_index(SLV2Plugin p, + uint32_t index) +{ + return raptor_sequence_get_at(p->ports, (int)index); +} + + +SLV2Port +slv2_plugin_get_port_by_symbol(SLV2Plugin p, + const char* symbol) +{ + // FIXME: sort plugins and do a binary search + for (int i=0; i < raptor_sequence_size(p->ports); ++i) { + SLV2Port port = raptor_sequence_get_at(p->ports, i); + if (!strcmp(port->symbol, symbol)) + return port; + } + + return NULL; +} + diff --git a/src/plugininstance.c b/src/plugininstance.c index 906bfb8..6d957b6 100644 --- a/src/plugininstance.c +++ b/src/plugininstance.c @@ -42,13 +42,15 @@ slv2_plugin_instantiate(SLV2Plugin plugin, } const char* const lib_uri = slv2_plugin_get_library_uri(plugin); - if (!lib_uri || slv2_uri_to_path(lib_uri) == NULL) + const char* const lib_path = slv2_uri_to_path(lib_uri); + + if (!lib_path) return NULL; dlerror(); - void* lib = dlopen(slv2_uri_to_path(lib_uri), RTLD_NOW); + void* lib = dlopen(lib_path, RTLD_NOW); if (!lib) { - fprintf(stderr, "Unable to open library %s (%s)\n", lib_uri, dlerror()); + fprintf(stderr, "Unable to open library %s (%s)\n", lib_path, dlerror()); return NULL; } @@ -56,31 +58,34 @@ slv2_plugin_instantiate(SLV2Plugin plugin, if (!df) { fprintf(stderr, "Could not find symbol 'lv2_descriptor', " - "%s is not a LV2 plugin.\n", lib_uri); + "%s is not a LV2 plugin.\n", lib_path); dlclose(lib); return NULL; } else { // Search for plugin by URI - const char* const bundle_path = slv2_uri_to_path(plugin->bundle_url); + // FIXME: Kluge to get bundle path (containing directory of binary) + const char* const bundle_path = strrchr(plugin->binary_uri, '/') + 1; + printf("Bundle path: %s\n", bundle_path); for (uint32_t i=0; 1; ++i) { + const LV2_Descriptor* ld = df(i); - + if (!ld) { fprintf(stderr, "Did not find plugin %s in %s\n", - plugin->plugin_uri, plugin->lib_uri); + slv2_plugin_get_uri(plugin), lib_path); dlclose(lib); break; // return NULL - } else if (!strcmp(ld->URI, (char*)plugin->plugin_uri)) { - //printf("Found %s at index %u in:\n\t%s\n\n", plugin->plugin_uri, i, lib_path); + } else if (!strcmp(ld->URI, slv2_plugin_get_uri(plugin))) { + + printf("Found %s at index %u in:\n\t%s\n\n", + librdf_uri_as_string(plugin->plugin_uri), i, lib_path); assert(ld->instantiate); // Create SLV2Instance to return result = malloc(sizeof(struct _Instance)); - /*result->plugin = malloc(sizeof(struct _Plugin)); - memcpy(result->plugin, plugin, sizeof(struct _Plugin));*/ result->lv2_descriptor = ld; result->lv2_handle = ld->instantiate(ld, sample_rate, (char*)bundle_path, host_features); struct _InstanceImpl* impl = malloc(sizeof(struct _InstanceImpl)); diff --git a/src/pluginlist.c b/src/pluginlist.c index 9dcb33c..50bb2ad 100644 --- a/src/pluginlist.c +++ b/src/pluginlist.c @@ -17,7 +17,6 @@ */ #define _XOPEN_SOURCE 500 -#include #include #include #include @@ -25,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -32,21 +32,6 @@ #include #include "private_types.h" - -/* not exposed */ -struct _Plugin* -slv2_plugin_new() -{ - struct _Plugin* result = malloc(sizeof(struct _Plugin)); - result->plugin_uri = NULL; - result->bundle_url = NULL; - result->lib_uri = NULL; - - result->data_uris = slv2_strings_new(); - - return result; -} - SLV2Plugins slv2_plugins_new() @@ -61,7 +46,7 @@ slv2_plugins_free(SLV2Plugins list) raptor_free_sequence(list); } - +#if 0 void slv2_plugins_filter(SLV2Plugins dest, SLV2Plugins source, bool (*include)(SLV2Plugin)) { @@ -127,30 +112,33 @@ slv2_plugins_load_bundle(SLV2Plugins list, else strcat((char*)manifest_url, "/manifest.ttl"); - rasqal_query_results *results; - raptor_uri *base_url = raptor_new_uri(manifest_url); - rasqal_query *rq = rasqal_new_query("sparql", NULL); - + librdf_query_results *results; + librdf_uri *base_uri = librdf_new_uri(slv2_rdf_world, manifest_url); + /* Get all plugins explicitly mentioned in the manifest (discovery pass 1) */ char* query_string = "PREFIX : \n\n" "SELECT DISTINCT ?plugin_uri FROM <>\n" "WHERE { ?plugin_uri a :Plugin }\n"; + + librdf_query *rq = librdf_new_query(slv2_rdf_world, "sparql", NULL, + (unsigned char*)query_string, base_uri); + + //printf("%s\n\n", query_string); - rasqal_query_prepare(rq, (unsigned char*)query_string, base_url); - results = rasqal_query_execute(rq); + results = librdf_query_execute(rq, model->model); - while (!rasqal_query_results_finished(results)) { + while (!librdf_query_results_finished(results)) { - rasqal_literal* literal = rasqal_query_results_get_binding_value(results, 0); + librdf_node* literal = librdf_query_results_get_binding_value(results, 0); assert(literal); - if (!slv2_plugins_get_by_uri(list, (const char*)rasqal_literal_as_string(literal))) { + if (!slv2_plugins_get_by_uri(list, (const char*)librdf_node_get_literal_value(literal))) { /* Create a new plugin */ struct _Plugin* new_plugin = slv2_plugin_new(); - new_plugin->plugin_uri = strdup((const char*)rasqal_literal_as_string(literal)); + new_plugin->plugin_uri = strdup((const char*)librdf_node_get_literal_value(literal)); new_plugin->bundle_url = strdup(bundle_base_url); raptor_sequence_push(new_plugin->data_uris, strdup((const char*)manifest_url)); @@ -158,15 +146,13 @@ slv2_plugins_load_bundle(SLV2Plugins list, } - rasqal_query_results_next(results); + librdf_query_results_next(results); } if (results) - rasqal_free_query_results(results); - - rasqal_free_query(rq); + librdf_free_query_results(results); - rq = rasqal_new_query("sparql", NULL); + librdf_free_query(rq); /* Get all data files linked to plugins (discovery pass 2) */ query_string = @@ -175,22 +161,24 @@ slv2_plugins_load_bundle(SLV2Plugins list, "SELECT DISTINCT ?subject ?data_uri ?binary FROM <>\n" "WHERE { ?subject rdfs:seeAlso ?data_uri\n" "OPTIONAL { ?subject :binary ?binary } }\n"; + + rq = librdf_new_query(slv2_rdf_world, "sparql", NULL, + (unsigned char*)query_string, base_uri); //printf("%s\n\n", query_string); - rasqal_query_prepare(rq, (unsigned char*)query_string, base_url); - results = rasqal_query_execute(rq); + results = librdf_query_execute(rq, slv2_model); - while (!rasqal_query_results_finished(results)) { + while (!librdf_query_results_finished(results)) { - const char* subject = (const char*)rasqal_literal_as_string( - rasqal_query_results_get_binding_value(results, 0)); + const char* subject = (const char*)librdf_node_get_literal_value( + librdf_query_results_get_binding_value(results, 0)); - const char* data_uri = (const char*)rasqal_literal_as_string( - rasqal_query_results_get_binding_value(results, 1)); + const char* data_uri = (const char*)librdf_node_get_literal_value( + librdf_query_results_get_binding_value(results, 1)); - const char* binary = (const char*)rasqal_literal_as_string( - rasqal_query_results_get_binding_value(results, 2)); + const char* binary = (const char*)librdf_node_get_literal_value( + librdf_query_results_get_binding_value(results, 2)); SLV2Plugin plugin = slv2_plugins_get_by_uri(list, subject); @@ -200,16 +188,16 @@ slv2_plugins_load_bundle(SLV2Plugins list, if (plugin && binary && !plugin->lib_uri) ((struct _Plugin*)plugin)->lib_uri = strdup(binary); - rasqal_query_results_next(results); + librdf_query_results_next(results); } if (results) - rasqal_free_query_results(results); + librdf_free_query_results(results); - rasqal_free_query(rq); + librdf_free_query(rq); - raptor_free_uri(base_url); + librdf_free_uri(base_uri); free(manifest_url); } @@ -275,7 +263,7 @@ slv2_plugins_load_path(SLV2Plugins list, free(path); } - +#endif unsigned slv2_plugins_size(SLV2Plugins list) @@ -287,10 +275,28 @@ slv2_plugins_size(SLV2Plugins list) SLV2Plugin slv2_plugins_get_by_uri(SLV2Plugins list, const char* uri) { - for (int i=0; i < raptor_sequence_size(list); ++i) { + // good old fashioned binary search + + int lower = 0; + int upper = raptor_sequence_size(list) - 1; + int i; + + if (upper == 0) + return NULL; + + while (upper >= lower) { + i = lower + ((upper - lower) / 2); + SLV2Plugin p = raptor_sequence_get_at(list, i); - if (!strcmp(p->plugin_uri, uri)) + + int cmp = strcmp(slv2_plugin_get_uri(p), uri); + + if (cmp == 0) return p; + else if (cmp > 0) + upper = i - 1; + else + lower = i + 1; } return NULL; diff --git a/src/port.c b/src/port.c index 71b55a9..97fb800 100644 --- a/src/port.c +++ b/src/port.c @@ -25,35 +25,49 @@ #include #include #include +#include "private_types.h" -SLV2PortID -slv2_port_by_index(uint32_t index) +/* private */ +SLV2Port +slv2_port_new(uint32_t index, const char* symbol/*, const char* node_id*/) { - SLV2PortID ret; - ret.is_index = true; - ret.index = index; - ret.symbol = NULL; - return ret; + struct _Port* port = malloc(sizeof(struct _Port)); + port->index = index; + port->symbol = strdup(symbol); + //port->node_id = strdup(node_id); + return port; } -SLV2PortID -slv2_port_by_symbol(const char* symbol) +/* private */ +void +slv2_port_free(SLV2Port port) { - SLV2PortID ret; - ret.is_index = false; - ret.index = UINT_MAX; - ret.symbol = symbol; - return ret; + free(port->symbol); + //free(port->node_id); + free(port); +} + + +/* private */ +SLV2Port +slv2_port_duplicate(SLV2Port port) +{ + struct _Port* result = malloc(sizeof(struct _Port)); + result->index = port->index; + result->symbol = strdup(port->symbol); + //result->node_id = strdup(port->node_id); + return result; } SLV2PortClass slv2_port_get_class(SLV2Plugin p, - SLV2PortID id) + SLV2Port port) { - SLV2Strings class = slv2_port_get_value(p, id, "rdf:type"); + SLV2Strings class = slv2_port_get_value(p, port, "rdf:type"); + assert(class); SLV2PortClass ret = SLV2_UNKNOWN_PORT_CLASS; @@ -98,152 +112,129 @@ slv2_port_get_class(SLV2Plugin p, SLV2Strings slv2_port_get_value(SLV2Plugin p, - SLV2PortID id, + SLV2Port port, const char* property) { assert(property); SLV2Strings result = NULL; - if (id.is_index) { - char index_str[16]; - snprintf(index_str, (size_t)16, "%u", id.index); - - char* query = slv2_strjoin( - "SELECT DISTINCT ?value WHERE { \n" - "plugin: lv2:port ?port . \n" - "?port lv2:index ", index_str, " ;\n\t", - property, " ?value . \n}\n", NULL); + char* query = slv2_strjoin( + "SELECT DISTINCT ?value WHERE {\n" + "?port lv2:symbol \"", port->symbol, "\";\n\t", + property, " ?value .\n}", 0); + + result = slv2_plugin_simple_query(p, query, "value"); - result = slv2_plugin_simple_query(p, query, "value"); - - free(query); + free(query); - } else { - - char* query = slv2_strjoin( - "SELECT DISTINCT ?value WHERE { \n" - "plugin: lv2:port ?port . \n" - "?port lv2:symbol \"", id.symbol, "\" ;\n\t", - property, " ?value . \n}\n", NULL); - - result = slv2_plugin_simple_query(p, query, "value"); - - free(query); - } - return result; } char* slv2_port_get_symbol(SLV2Plugin p, - SLV2PortID id) + SLV2Port port) { - char* result = NULL; + char* symbol = NULL; - SLV2Strings prop - = slv2_port_get_value(p, id, "lv2:symbol"); + SLV2Strings result = slv2_port_get_value(p, port, "lv2:symbol"); - if (prop && slv2_strings_size(prop) == 1) - result = strdup(slv2_strings_get_at(prop, 0)); + if (result && slv2_strings_size(result) == 1) + symbol = strdup(slv2_strings_get_at(result, 0)); - slv2_strings_free(prop); + slv2_strings_free(result); - return result; + return symbol; } char* slv2_port_get_name(SLV2Plugin p, - SLV2PortID id) + SLV2Port port) { - char* result = NULL; + char* name = NULL; - SLV2Strings prop - = slv2_port_get_value(p, id, "lv2:name"); + SLV2Strings result = slv2_port_get_value(p, port, "lv2:name"); - if (prop && slv2_strings_size(prop) == 1) - result = strdup(slv2_strings_get_at(prop, 0)); + if (result && slv2_strings_size(result) == 1) + name = strdup(slv2_strings_get_at(result, 0)); - slv2_strings_free(prop); + slv2_strings_free(result); - return result; + return name; } float slv2_port_get_default_value(SLV2Plugin p, - SLV2PortID id) + SLV2Port port) { // FIXME: do casting properly in the SPARQL query - float result = 0.0f; + float value = 0.0f; - SLV2Strings prop - = slv2_port_get_value(p, id, "lv2:default"); + SLV2Strings result = slv2_port_get_value(p, port, "lv2:default"); - if (prop && slv2_strings_size(prop) == 1) - result = atof(slv2_strings_get_at(prop, 0)); + if (result && slv2_strings_size(result) == 1) + value = atof(slv2_strings_get_at(result, 0)); - slv2_strings_free(prop); + slv2_strings_free(result); - return result; + return value; } float slv2_port_get_minimum_value(SLV2Plugin p, - SLV2PortID id) + SLV2Port port) { - // FIXME: do casting properly in the SPARQL query + // FIXME: need better access to literal types - float result = 0.0f; + float value = 0.0f; - SLV2Strings prop - = slv2_port_get_value(p, id, "lv2:minimum"); + SLV2Strings result = slv2_port_get_value(p, port, "lv2:minimum"); - if (prop && slv2_strings_size(prop) == 1) - result = atof(slv2_strings_get_at(prop, 0)); + if (result && slv2_strings_size(result) == 1) + value = atof(slv2_strings_get_at(result, 0)); - slv2_strings_free(prop); + slv2_strings_free(result); - return result; + return value; } float slv2_port_get_maximum_value(SLV2Plugin p, - SLV2PortID id) + SLV2Port port) { - // FIXME: do casting properly in the SPARQL query + // FIXME: need better access to literal types - float result = 0.0f; + float value = 0.0f; - SLV2Strings prop - = slv2_port_get_value(p, id, "lv2:maximum"); + SLV2Strings result = slv2_port_get_value(p, port, "lv2:maximum"); - if (prop && slv2_strings_size(prop) == 1) - result = atof(slv2_strings_get_at(prop, 0)); + if (result && slv2_strings_size(result) == 1) + value = atof(slv2_strings_get_at(result, 0)); - slv2_strings_free(prop); + slv2_strings_free(result); - return result; + return value; } SLV2Strings slv2_port_get_properties(SLV2Plugin p, - SLV2PortID id) + SLV2Port port) { - return slv2_port_get_value(p, id, "lv2:portProperty"); + return slv2_port_get_value(p, port, "lv2:portProperty"); } SLV2Strings slv2_port_get_hints(SLV2Plugin p, - SLV2PortID id) + SLV2Port port) { - return slv2_port_get_value(p, id, "lv2:portHint"); + return slv2_port_get_value(p, port, "lv2:portHint"); } diff --git a/src/private_types.h b/src/private_types.h index 027d68d..12f74cb 100644 --- a/src/private_types.h +++ b/src/private_types.h @@ -25,13 +25,21 @@ extern "C" { #include #include -#include -#include +#include +#include -/** The URI of the lv2.ttl file. +/** Reference to a port on some plugin. */ -extern raptor_uri* slv2_ontology_uri; +struct _Port { + uint32_t index; ///< LV2 index + char* symbol; ///< LV2 symbol + //char* node_id; ///< RDF Node ID +}; + +SLV2Port slv2_port_new(uint32_t index, const char* symbol/*, const char* node_id*/); +SLV2Port slv2_port_duplicate(SLV2Port port); +void slv2_port_free(SLV2Port port); /** Record of an installed/available plugin. @@ -40,28 +48,42 @@ extern raptor_uri* slv2_ontology_uri; * paths of relevant files, the actual data therein isn't loaded into memory. */ struct _Plugin { - char* plugin_uri; - char* bundle_url; // Bundle directory plugin was loaded from + int deletable; + struct _Model* model; + librdf_uri* plugin_uri; +// char* bundle_url; // Bundle directory plugin was loaded from + char* binary_uri; // lv2:binary raptor_sequence* data_uris; // rdfs::seeAlso - char* lib_uri; // lv2:binary + raptor_sequence* ports; + librdf_storage* storage; + librdf_model* rdf; }; - -/** Pimpl portion of SLV2Instance */ -struct _InstanceImpl { - void* lib_handle; -}; +SLV2Plugin slv2_plugin_new(SLV2Model model, librdf_uri* uri, const char* binary_uri); +void slv2_plugin_load(SLV2Plugin p); -/** List of references to plugins available for loading (private type) */ +/** List of references to plugins available for loading */ struct _PluginList { size_t num_plugins; struct _Plugin** plugins; }; +/** Pimpl portion of SLV2Instance */ +struct _InstanceImpl { + void* lib_handle; +}; -/** An ordered, indexable collection of strings. */ -//typedef raptor_sequence* SLV2Strings; + +/** Model of LV2 (RDF) data loaded from bundles. + */ +struct _Model { + librdf_world* world; + librdf_storage* storage; + librdf_model* model; + librdf_parser* parser; + SLV2Plugins plugins; +}; #ifdef __cplusplus diff --git a/src/query.c b/src/query.c index df0f6d4..7127a8d 100644 --- a/src/query.c +++ b/src/query.c @@ -20,40 +20,20 @@ #include #include #include -#include +#include #include -#include #include #include #include "private_types.h" -char* -slv2_query_header(SLV2Plugin p) -{ - const char* const plugin_uri = slv2_plugin_get_uri(p); - //SLV2Strings files = slv2_plugin_get_data_uris(p); - - char* query_string = slv2_strjoin( - "PREFIX rdf: \n" - "PREFIX rdfs: \n" - "PREFIX doap: \n" - "PREFIX lv2: \n" - "PREFIX plugin: <", plugin_uri, ">\n", NULL); - - /*for (int i=0; i < slv2_strings_size(files); ++i) { - const char* file_uri = slv2_strings_get_at(files, i); - slv2_strappend(&query_string, "PREFIX data: <"); - slv2_strappend(&query_string, file_uri); - slv2_strappend(&query_string, ">\n"); - }*/ - - slv2_strappend(&query_string, "\n"); - - return query_string; -} - +static const char* slv2_query_prefixes = + "PREFIX rdf: \n" + "PREFIX rdfs: \n" + "PREFIX doap: \n" + "PREFIX lv2: \n"; +#if 0 char* slv2_query_lang_filter(const char* variable) { @@ -69,26 +49,48 @@ slv2_query_lang_filter(const char* variable) return result; } - +#endif SLV2Strings -slv2_query_get_variable_bindings(rasqal_query_results* results, +slv2_query_get_variable_bindings(librdf_query_results* results, const char* variable) { SLV2Strings result = NULL; - if (rasqal_query_results_get_bindings_count(results) > 0) + if (librdf_query_results_get_bindings_count(results) > 0) result = slv2_strings_new(); - while (!rasqal_query_results_finished(results)) { - - rasqal_literal* literal = - rasqal_query_results_get_binding_value_by_name(results, (const unsigned char*)variable); - assert(literal != NULL); - - raptor_sequence_push(result, strdup((const char*)rasqal_literal_as_string(literal))); - - rasqal_query_results_next(results); + while (!librdf_query_results_finished(results)) { + + librdf_node* node = + librdf_query_results_get_binding_value_by_name(results, variable); + + char* str = NULL; + + switch (librdf_node_get_type(node)) { + case LIBRDF_NODE_TYPE_RESOURCE: + str = strdup((const char*)librdf_uri_as_string(librdf_node_get_uri(node))); + break; + case LIBRDF_NODE_TYPE_LITERAL: + str = strdup((const char*)librdf_node_get_literal_value(node)); + break; + case LIBRDF_NODE_TYPE_BLANK: + str = strdup((const char*)librdf_node_get_blank_identifier(node)); + break; + case LIBRDF_NODE_TYPE_UNKNOWN: + default: + fprintf(stderr, "Unknown variable binding type for ?%s\n", variable); + break; + } + + if (str) { + //printf("?%s = %s\n", variable, str); + raptor_sequence_push(result, str); + } + + librdf_free_node(node); + + librdf_query_results_next(results); } return result; @@ -96,70 +98,61 @@ slv2_query_get_variable_bindings(rasqal_query_results* results, size_t -slv2_query_count_bindings(rasqal_query_results* results) +slv2_query_count_bindings(librdf_query_results* results) { size_t count = 0; - while (!rasqal_query_results_finished(results)) { + while (!librdf_query_results_finished(results)) { ++count; - rasqal_query_results_next(results); + librdf_query_results_next(results); } return count; } -rasqal_query_results* -slv2_plugin_query(SLV2Plugin plugin, +librdf_query_results* +slv2_plugin_query(SLV2Plugin plugin, const char* sparql_str) { - raptor_uri* base_uri = raptor_new_uri((unsigned char*)slv2_plugin_get_uri(plugin)); + if (!plugin->rdf) + slv2_plugin_load(plugin); + + librdf_uri* base_uri = plugin->plugin_uri; + + char* query_str = slv2_strjoin(slv2_query_prefixes, sparql_str, NULL); - rasqal_query *rq = rasqal_new_query("sparql", NULL); + //printf("******** Query \n%s********\n", query_str); + + librdf_query *rq = librdf_new_query(plugin->model->world, "sparql", NULL, + (const unsigned char*)query_str, base_uri); if (!rq) { - fprintf(stderr, "ERROR: Could not create Rasqal query\n"); + fprintf(stderr, "ERROR: Could not create query\n"); return NULL; } - - char* header = slv2_query_header(plugin); - char* query_str = slv2_strjoin(header, sparql_str, NULL); - - //printf("Query: \n%s\n\n", query_str); - - rasqal_query_prepare(rq, (unsigned char*)query_str, base_uri); // Add LV2 ontology to query sources - rasqal_query_add_data_graph(rq, slv2_ontology_uri, - NULL, RASQAL_DATA_GRAPH_BACKGROUND); + //librdf_query_add_data_graph(rq, slv2_ontology_uri, + // NULL, RASQAL_DATA_GRAPH_BACKGROUND); // Add all plugin data files to query sources - for (unsigned i=0; i < slv2_strings_size(plugin->data_uris); ++i) { + /*for (unsigned i=0; i < slv2_strings_size(plugin->data_uris); ++i) { const char* file_uri_str = slv2_strings_get_at(plugin->data_uris, i); raptor_uri* file_uri = raptor_new_uri((const unsigned char*)file_uri_str); - rasqal_query_add_data_graph(rq, file_uri, + librdf_query_add_data_graph(rq, file_uri, NULL, RASQAL_DATA_GRAPH_BACKGROUND); raptor_free_uri(file_uri); - } + }*/ - rasqal_query_results* results = rasqal_query_execute(rq); + librdf_query_results* results = librdf_query_execute(rq, plugin->rdf); - rasqal_free_query(rq); - raptor_free_uri(base_uri); + librdf_free_query(rq); - free(header); free(query_str); // FIXME: results leaked internally in places? return results; - - /* - SLV2Strings ret = slv2_query_get_variable_bindings(results, var_name); - - rasqal_free_query_results(results); - rasqal_free_query(rq); - - return ret;*/ } @@ -169,9 +162,9 @@ slv2_plugin_simple_query(SLV2Plugin plugin, const char* sparql_str, const char* variable) { - rasqal_query_results* results = slv2_plugin_query(plugin, sparql_str); + librdf_query_results* results = slv2_plugin_query(plugin, sparql_str); SLV2Strings ret = slv2_query_get_variable_bindings(results, variable); - rasqal_free_query_results(results); + librdf_free_query_results(results); return ret; } @@ -186,11 +179,11 @@ unsigned slv2_plugin_query_count(SLV2Plugin plugin, const char* sparql_str) { - rasqal_query_results* results = slv2_plugin_query(plugin, sparql_str); + librdf_query_results* results = slv2_plugin_query(plugin, sparql_str); if (results) { unsigned ret = slv2_query_count_bindings(results); - rasqal_free_query_results(results); + librdf_free_query_results(results); return ret; } else { return 0; @@ -202,34 +195,29 @@ size_t slv2_query_count_results(SLV2Plugin p, const char* query) { - char* header = slv2_query_header(p); - char* query_str = slv2_strjoin(header, query, NULL); + char* query_str = slv2_strjoin(slv2_query_prefixes, query, NULL); assert(p); assert(query_str); - rasqal_query *rq = rasqal_new_query("sparql", NULL); + librdf_query *rq = librdf_new_query(p->model->world, "sparql", NULL, + (unsigned char*)query_str, NULL); //printf("Query: \n%s\n\n", query_str); - rasqal_query_prepare(rq, (unsigned char*)query_str, NULL); - // Add LV2 ontology to query sources - rasqal_query_add_data_graph(rq, slv2_ontology_uri, - NULL, RASQAL_DATA_GRAPH_BACKGROUND); + //librdf_query_add_data_graph(rq, slv2_ontology_uri, + // NULL, RASQAL_DATA_GRAPH_BACKGROUND); - rasqal_query_results* results = rasqal_query_execute(rq); + librdf_query_results* results = librdf_query_execute(rq, p->model->model); assert(results); size_t count = slv2_query_count_bindings(results); - rasqal_free_query_results(results); - rasqal_free_query(rq); - - rasqal_finish(); + librdf_free_query_results(results); + librdf_free_query(rq); free(query_str); - free(header); return count; } -- cgit v1.2.1