From 056f394151a48e9d129691fd7451a3d0bcbde3ba Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 3 Sep 2006 05:11:57 +0000 Subject: Saner (internal) query API, though still needs work. Preliminary (untested) support for host features/extensions/whatever. Documentation fixes and minor cleanups. git-svn-id: http://svn.drobilla.net/lad/libslv2@113 a436a847-0d15-0410-975c-d299462d15a1 --- slv2/plugin.h | 44 ++++++++++++++++++++ slv2/query.h | 25 ++++++++---- src/plugin.c | 110 ++++++++++++++++++++++++++++++++++---------------- src/port.c | 14 ++----- src/query.c | 127 ++++++++++++++++++++++++++++++++++++++++++---------------- 5 files changed, 233 insertions(+), 87 deletions(-) diff --git a/slv2/plugin.h b/slv2/plugin.h index 57fa266..95d933e 100644 --- a/slv2/plugin.h +++ b/slv2/plugin.h @@ -179,6 +179,50 @@ slv2_plugin_has_latency(const SLV2Plugin* p); uint32_t slv2_plugin_get_latency_port(const SLV2Plugin* p); +#if 0 +/** Return whether or not a plugin supports the given host feature / extension. + * + * This will return true for both supported and required host features. + */ +bool +slv2_plugin_supports_feature(const SLV2Plugin* p, const char* feature_uri); + + +/** Return whether or not a plugin requires the given host feature / extension. + * + * If a plugin requires a feature, that feature MUST be passed to the plugin's + * instantiate method or the plugin will fail to instantiate. + */ +bool +slv2_plugin_requires_features(const SLV2Plugin* p, const char* feature_uri); +#endif + +/** Get a plugin's supported host features / extensions. + * + * This returns a list of all supported features (both required and optional). + */ +SLV2Property +slv2_plugin_get_supported_features(const SLV2Plugin* p); + + +/** Get a plugin's requires host features / extensions. + * + * All feature URI's returned by this call MUST be passed to the plugin's + * instantiate method for the plugin to instantiate successfully. + */ +SLV2Property +slv2_plugin_get_required_features(const SLV2Plugin* p); + + +/** Get a plugin's optional host features / extensions. + * + * If the feature URI's returned by this method are passed to the plugin's + * instantiate method, those features will be used by the function, otherwise + * the plugin will act as it would if it did not support that feature at all. + */ +SLV2Property +slv2_plugin_get_optional_features(const SLV2Plugin* p); + /** @} */ diff --git a/slv2/query.h b/slv2/query.h index 9f1c93d..a23df0e 100644 --- a/slv2/query.h +++ b/slv2/query.h @@ -74,23 +74,32 @@ char* slv2_query_lang_filter(const char* variable); -/** Run a SPARQL query on a plugin's data file. +/** Run a SPARQL query on a plugin's data file and return variable matches. * * Header from slv2query_header will be prepended to passed query string (so * the default prefixes will be already defined, you don't need to add them * yourself). * - * rasqal_init() must be called by the caller before calling this function. + * Returned is a list of all matches for the query variable \a var_name. */ -rasqal_query_results* -slv2_plugin_run_query(const SLV2Plugin* p, - const char* query_string); +SLV2Property +slv2_query_get_results(const SLV2Plugin* p, + const char* query_string, + const char* var_name); + +/** Run a SPARQL query on a plugin's data file and just count the matches. + * + * Header from slv2query_header will be prepended to passed query string (so + * the default prefixes will be already defined, you don't need to add them + * yourself). + * + * Returned is the total of all variable matches resulting from the query. + */ size_t -slv2_query_get_num_results(rasqal_query_results* results, const char* var_name); +slv2_query_count_results(const SLV2Plugin* p, + const char* query_string); -SLV2Property -slv2_query_get_results(rasqal_query_results* results, const char* var_name); /** Free an SLV2Property. */ void diff --git a/src/plugin.c b/src/plugin.c index a024077..65903da 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -130,7 +130,6 @@ SLV2Property slv2_plugin_get_property(const SLV2Plugin* p, const char* property) { - assert(p); assert(property); /* @@ -147,19 +146,13 @@ slv2_plugin_get_property(const SLV2Plugin* p, free(header); free(lang_filter);*/ - rasqal_init(); - char* query = strjoin( "SELECT DISTINCT ?value FROM data: WHERE { \n" "plugin: ", property, " ?value . \n" "} \n", NULL); - rasqal_query_results* results = slv2_plugin_run_query(p, query); + SLV2Property result = slv2_query_get_results(p, query, "value"); - SLV2Property result = slv2_query_get_results(results, "value"); - - rasqal_free_query_results(results); - rasqal_finish(); free(query); return result; @@ -169,54 +162,45 @@ slv2_plugin_get_property(const SLV2Plugin* p, uint32_t slv2_plugin_get_num_ports(const SLV2Plugin* p) { - rasqal_init(); - char* query = strjoin( "SELECT DISTINCT ?value FROM data: WHERE { \n" "plugin: lv2:port ?value . \n" "} \n", NULL); - rasqal_query_results* results = slv2_plugin_run_query(p, query); - const size_t result = slv2_query_get_num_results(results, "value"); + SLV2Property results = slv2_query_get_results(p, query, "value"); + + size_t count = results->num_values; - rasqal_free_query_results(results); - rasqal_finish(); free(query); + slv2_property_free(results); - return result; + return count; } bool slv2_plugin_has_latency(const SLV2Plugin* p) { - assert(p); - - rasqal_init(); - char* query = "SELECT DISTINCT ?value FROM data: WHERE { \n" " plugin: lv2:port ?port . \n" " ?port lv2:portHint lv2:reportsLatency . \n" "}\n"; - rasqal_query_results* results = slv2_plugin_run_query(p, query); - bool result = ( rasqal_query_results_get_bindings_count(results) > 0 ); + SLV2Property results = slv2_query_get_results(p, query, "port"); + + bool exists = (results->num_values > 0); - rasqal_free_query_results(results); - rasqal_finish(); - free(query); + free(query); + slv2_property_free(results); - return result; + return exists; } + uint32_t slv2_plugin_get_latency_port(const SLV2Plugin* p) { - assert(p); - - rasqal_init(); - char* query = "SELECT DISTINCT ?value FROM data: WHERE { \n" " plugin: lv2:port ?port . \n" @@ -224,9 +208,7 @@ slv2_plugin_get_latency_port(const SLV2Plugin* p) " lv2:index ?index . \n" "}\n"; - rasqal_query_results* results = slv2_plugin_run_query(p, query); - - struct _Property* result = slv2_query_get_results(results, "index"); + SLV2Property result = slv2_query_get_results(p, query, "index"); // FIXME: need a sane error handling strategy assert(result->num_values == 1); @@ -234,10 +216,70 @@ slv2_plugin_get_latency_port(const SLV2Plugin* p) uint32_t index = strtol(result->values[0], &endptr, 10); // FIXME: check.. stuff.. - rasqal_free_query_results(results); - rasqal_finish(); free(query); return index; } +/* +bool +slv2_plugin_supports_feature(const SLV2Plugin* p, const char* feature_uri) +{ +} + + +bool +slv2_plugin_requires_feature(const SLV2Plugin* p, const char* feature_uri) +{ +} +*/ + +SLV2Property +slv2_plugin_get_supported_features(const SLV2Plugin* p) +{ + char* query = + "SELECT DISTINCT ?feature FROM data: WHERE { \n" + " { plugin: lv2:requiredHostFeature ?feature } \n" + " UNION \n" + " { plugin: lv2:supportedHostFeature ?feature } \n" + "}\n"; + + SLV2Property result = slv2_query_get_results(p, query, "feature"); + + free(query); + + return result; +} + + +SLV2Property +slv2_plugin_get_optional_features(const SLV2Plugin* p) +{ + char* query = + "SELECT DISTINCT ?feature FROM data: WHERE { \n" + " plugin: lv2:supportedHostFeature ?feature . \n" + "}\n"; + + SLV2Property result = slv2_query_get_results(p, query, "feature"); + + free(query); + + return result; +} + + +SLV2Property +slv2_plugin_get_required_features(const SLV2Plugin* p) +{ + char* query = + "SELECT DISTINCT ?feature FROM data: WHERE { \n" + " plugin: lv2:requiredHostFeature ?feature . \n" + "}\n"; + + SLV2Property result = slv2_query_get_results(p, query, "feature"); + + free(query); + + return result; +} + diff --git a/src/port.c b/src/port.c index 111517d..1ca149d 100644 --- a/src/port.c +++ b/src/port.c @@ -73,13 +73,10 @@ slv2_port_get_property(SLV2Plugin* p, uint32_t index, const char* property) { - assert(p); assert(property); - char index_str[4]; - snprintf(index_str, (size_t)4, "%u", index); - - rasqal_init(); + char index_str[16]; + snprintf(index_str, (size_t)16, "%u", index); char* query = strjoin( "SELECT DISTINCT ?value FROM data: WHERE { \n" @@ -87,12 +84,8 @@ slv2_port_get_property(SLV2Plugin* p, "?port lv2:index ", index_str, " . \n" "?port ", property, " ?value . \n}\n", NULL); - rasqal_query_results* results = slv2_plugin_run_query(p, query); + SLV2Property result = slv2_query_get_results(p, query, "value"); - SLV2Property result = slv2_query_get_results(results, "value"); - - rasqal_free_query_results(results); - rasqal_finish(); free(query); return result; @@ -103,7 +96,6 @@ char* slv2_port_get_symbol(SLV2Plugin* p, uint32_t index) { - // FIXME: leaks char* result = NULL; SLV2Property prop diff --git a/src/query.c b/src/query.c index 56903ac..177d06e 100644 --- a/src/query.c +++ b/src/query.c @@ -58,9 +58,55 @@ slv2_query_lang_filter(const char* variable) } -rasqal_query_results* -slv2_plugin_run_query(const SLV2Plugin* p, - const char* query) +SLV2Property +slv2_query_get_variable_bindings(rasqal_query_results* results, const char* var_name) +{ + struct _Property* result = NULL; + + if (rasqal_query_results_get_bindings_count(results) > 0) { + result = malloc(sizeof(struct _Property)); + result->num_values = 0; + result->values = NULL; + } + + while (!rasqal_query_results_finished(results)) { + + rasqal_literal* literal = + rasqal_query_results_get_binding_value_by_name(results, (const unsigned char*)var_name); + assert(literal != NULL); + + // Add value on to the array, reallocing all the way. + // Yes, this is disgusting. Roughly as disgusting as the rasqal query + // results API. coincidentally. + result->num_values++; + result->values = realloc(result->values, result->num_values * sizeof(char*)); + result->values[result->num_values-1] = strdup((const char*)rasqal_literal_as_string(literal)); + + rasqal_query_results_next(results); + } + + return result; +} + + +size_t +slv2_query_count_variable_bindings(rasqal_query_results* results) +{ + size_t count = 0; + + while (!rasqal_query_results_finished(results)) { + ++count; + rasqal_query_results_next(results); + } + + return count; +} + + +SLV2Property +slv2_query_get_results(const SLV2Plugin* p, + const char* query, + const char* var_name) { char* header = slv2_query_header(p); char* query_str = strjoin(header, query, NULL); @@ -68,21 +114,63 @@ slv2_plugin_run_query(const SLV2Plugin* p, assert(p); assert(query_str); + rasqal_init(); + rasqal_query *rq = rasqal_new_query("sparql", NULL); //printf("Query: \n%s\n\n", query_str); rasqal_query_prepare(rq, (unsigned char*)query_str, NULL); rasqal_query_results* results = rasqal_query_execute(rq); + assert(results); + SLV2Property ret = slv2_query_get_variable_bindings(results, var_name); + rasqal_free_query_results(results); rasqal_free_query(rq); + rasqal_finish(); + free(query_str); free(header); + + return ret; +} + + +size_t +slv2_query_count_results(const SLV2Plugin* p, + const char* query) +{ + char* header = slv2_query_header(p); + char* query_str = strjoin(header, query, NULL); + + assert(p); + assert(query_str); + + rasqal_init(); + + rasqal_query *rq = rasqal_new_query("sparql", NULL); + + //printf("Query: \n%s\n\n", query_str); + + rasqal_query_prepare(rq, (unsigned char*)query_str, NULL); + rasqal_query_results* results = rasqal_query_execute(rq); + assert(results); - return results; + size_t count = slv2_query_count_variable_bindings(results); + + rasqal_free_query_results(results); + rasqal_free_query(rq); + + rasqal_finish(); + + free(query_str); + free(header); + + return count; } +/* size_t slv2_query_get_num_results(rasqal_query_results* results, const char* var_name) { @@ -97,36 +185,7 @@ slv2_query_get_num_results(rasqal_query_results* results, const char* var_name) return result; } - -SLV2Property -slv2_query_get_results(rasqal_query_results* results, const char* var_name) -{ - struct _Property* result = NULL; - - if (rasqal_query_results_get_bindings_count(results) > 0) { - result = malloc(sizeof(struct _Property)); - result->num_values = 0; - result->values = NULL; - } - - while (!rasqal_query_results_finished(results)) { - - rasqal_literal* literal = - rasqal_query_results_get_binding_value_by_name(results, (const unsigned char*)var_name); - assert(literal != NULL); - - // Add value on to the array, reallocing all the way. - // Yes, this is disgusting. Roughly as disgusting as the rasqal query - // results API. coincidentally. - result->num_values++; - result->values = realloc(result->values, result->num_values * sizeof(char*)); - result->values[result->num_values-1] = strdup((const char*)rasqal_literal_as_string(literal)); - - rasqal_query_results_next(results); - } - - return result; -} +*/ void slv2_property_free(struct _Property* prop) -- cgit v1.2.1