From f6ff6e487201bdd94e584397ce829daaa424aba9 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 8 May 2007 03:30:37 +0000 Subject: Reworked simple query API to allow passing either QName or URI predicates. Hack around a Rasqal bug for the above (URI predicates). Clean up exposed names for greppability and to not violate user namespace. Fixed slv2_plugin_get_value and slv2_plugin_get_value_for_resource. git-svn-id: http://svn.drobilla.net/lad/slv2@517 a436a847-0d15-0410-975c-d299462d15a1 --- slv2/plugin.h | 10 +++++++- slv2/plugins.h | 4 +--- slv2/types.h | 27 +++++++++++++++++----- slv2/value.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++++- src/plugin.c | 66 ++++++++++++++++++++++++++++++++++++++--------------- src/pluginclass.c | 2 +- src/pluginclasses.c | 3 ++- src/port.c | 4 ++-- src/slv2_internal.h | 34 +++++++++++++-------------- src/value.c | 57 +++++++++++++++++++++++++++++++++++++++++++-- src/world.c | 4 ++-- utils/lv2_inspect.c | 21 ++++++++++++++++- 12 files changed, 240 insertions(+), 55 deletions(-) diff --git a/slv2/plugin.h b/slv2/plugin.h index 7e7c928..ace6e3b 100644 --- a/slv2/plugin.h +++ b/slv2/plugin.h @@ -137,10 +137,14 @@ slv2_plugin_get_class(SLV2Plugin plugin); * * Return value must be freed by caller with slv2_values_free. * + * \a predicate must be either a URI or a QName. + * See \ref SLV2URIType documentation for examples. + * * Time = Query */ SLV2Values slv2_plugin_get_value(SLV2Plugin p, + SLV2URIType predicate_type, const char* predicate); @@ -156,13 +160,17 @@ slv2_plugin_get_value(SLV2Plugin p, * May return NULL if the property was not found, or if object is not * sensibly represented as an SLV2Values (e.g. blank nodes). * + * \a predicate must be either a URI or a QName. + * See \ref SLV2URIType documentation for examples. + * * Return value must be freed by caller with slv2_values_free. * * Time = Query */ SLV2Values slv2_plugin_get_value_for_subject(SLV2Plugin p, - const char* subject, + SLV2Value subject, + SLV2URIType predicate_type, const char* predicate); diff --git a/slv2/plugins.h b/slv2/plugins.h index 2101eee..5663d6a 100644 --- a/slv2/plugins.h +++ b/slv2/plugins.h @@ -19,6 +19,7 @@ #ifndef __SLV2_PLUGINS_H__ #define __SLV2_PLUGINS_H__ +#include #include #ifdef __cplusplus @@ -35,9 +36,6 @@ extern "C" { */ -typedef void* SLV2Plugins; - - /** Free a plugin list. * * Freeing a plugin list does not destroy the plugins it contains (plugins diff --git a/slv2/types.h b/slv2/types.h index d55b81d..e5c10e2 100644 --- a/slv2/types.h +++ b/slv2/types.h @@ -33,7 +33,7 @@ extern "C" { * to make the most common case simple. Use slv2_port_get_value(p, "rdf:type") * if you need further class information. */ -typedef enum _PortClass { +typedef enum _SLV2PortClass { SLV2_UNKNOWN_PORT_CLASS, SLV2_CONTROL_INPUT, /**< One input float per block */ SLV2_CONTROL_OUTPUT, /**< One output float per block */ @@ -44,20 +44,35 @@ typedef enum _PortClass { } SLV2PortClass; +/** The format of a URI string. + * + * Full URI: http://example.org/foo + * QName: lv2:Plugin + */ +typedef enum _SLV2URIType { + SLV2_URI, + SLV2_QNAME +} SLV2URIType; + + /** A port on a plugin. Opaque, but valid to compare to NULL. */ -typedef struct _Port* SLV2Port; +typedef struct _SLV2Port* SLV2Port; /** A plugin. Opaque, but valid to compare to NULL. */ -typedef struct _Plugin* SLV2Plugin; +typedef struct _SLV2Plugin* SLV2Plugin; + + +/** A collection of plugins. Opaque, but valid to compare to NULL. */ +typedef void* SLV2Plugins; /** The world. Opaque, but valid to compare to NULL. */ -typedef struct _World* SLV2World; +typedef struct _SLV2World* SLV2World; /** A plugin class. Opaque, but valid to compare to NULL. */ -typedef struct _PluginClass* SLV2PluginClass; +typedef struct _SLV2PluginClass* SLV2PluginClass; /** A collection of plugin classes. Opaque, but valid to compare to NULL. */ @@ -65,7 +80,7 @@ typedef void* SLV2PluginClasses; /** A typed value */ -typedef struct _Value* SLV2Value; +typedef struct _SLV2Value* SLV2Value; /** A collection of typed values. */ diff --git a/slv2/value.h b/slv2/value.h index abc7a57..2d0fb51 100644 --- a/slv2/value.h +++ b/slv2/value.h @@ -31,12 +31,48 @@ extern "C" { */ +#if 0 +/** Wrap a URI string (e.g. "http://example.org/foo") as an SLV2Value. + * + * The result is returned by value and refers directly to \a uri, it + * does not need to be freed by the caller - calling slv2_value_free + * on the returned value will destroy \a uri. + */ +SLV2Value +slv2_uri(const char* uri); + + +/** Wrap a QName string (e.g. "lv2:Plugin") as an SLV2Value. + * + * The result is returned by value and refers directly to \a uri, it + * does not need to be freed by the caller - calling slv2_value_free + * on the returned value will destroy \a qname. + */ +SLV2Value +slv2_qname(const char* qname); +#endif + + /** Return whether two values are equivalent. */ bool slv2_value_equals(SLV2Value value, SLV2Value other); +/** Return this value as a Turtle/SPARQL token. + * Examples: + * + * doap:name + * "this is a string" + * 1.0 + * 1 + * + * Returned string is newly allocation and must be freed by caller. + */ +char* +slv2_value_get_turtle_token(SLV2Value value); + + /** Return whether the value is a URI (resource). * * Time = O(1) @@ -47,7 +83,8 @@ slv2_value_is_uri(SLV2Value value); /** Return this value as a URI string, e.g. "http://example.org/foo". * - * Valid to call only if slv2_value_is_uri(\a value) returns true. + * Valid to call only if slv2_value_is_uri(\a value) or + * slv2_value_is_qname(\a value) returns true. * Returned value is owned by \a value and must not be freed by caller. * * Time = O(1) @@ -56,6 +93,30 @@ const char* slv2_value_as_uri(SLV2Value value); +#if 0 +/** Return whether the value is a QName ("qualified name", a prefixed URI). + * + * A QName will return true for both this, and slv2_value_is_uri. + * slv2_value_as_uri and slv2_value_as_qname will both return appropriately. + * + * Time = O(1) + */ +bool +slv2_value_is_qname(SLV2Value value); + + +/** Return this value as a QName string, e.g. "lv2:Plugin". + * + * Valid to call only if slv2_value_is_qname(\a value) returns true. + * Returned value is owned by \a value and must not be freed by caller. + * + * Time = O(1) + */ +const char* +slv2_value_as_qname(SLV2Value value); +#endif + + /** Return whether this value is a literal (i.e. not a URI). * * Returns true if \a value is a string or numeric value. diff --git a/src/plugin.c b/src/plugin.c index 6919513..391ed11 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -22,18 +22,20 @@ #include #include #include +#include "slv2_internal.h" #include #include #include #include -#include "slv2_internal.h" +#include +#include /* private */ SLV2Plugin slv2_plugin_new(SLV2World world, librdf_uri* uri, const char* binary_uri) { - struct _Plugin* plugin = malloc(sizeof(struct _Plugin)); + struct _SLV2Plugin* plugin = malloc(sizeof(struct _SLV2Plugin)); plugin->world = world; plugin->plugin_uri = librdf_new_uri_from_uri(uri); plugin->binary_uri = strdup(binary_uri); @@ -323,7 +325,7 @@ char* slv2_plugin_get_name(SLV2Plugin plugin) { char* result = NULL; - SLV2Values prop = slv2_plugin_get_value(plugin, "doap:name"); + SLV2Values prop = slv2_plugin_get_value(plugin, SLV2_QNAME, "doap:name"); // FIXME: lang? guaranteed to be the untagged one? if (prop && slv2_values_size(prop) > 0) { @@ -341,14 +343,25 @@ slv2_plugin_get_name(SLV2Plugin plugin) SLV2Values slv2_plugin_get_value(SLV2Plugin p, + SLV2URIType predicate_type, const char* predicate) { - assert(predicate); + char* query = NULL; + + /* Hack around broken RASQAL, full URI predicates don't work :/ */ - char* query = slv2_strjoin( - "SELECT DISTINCT ?value WHERE {" - "<> ", predicate, " ?value .\n" - "}\n", NULL); + if (predicate_type == SLV2_URI) { + query = slv2_strjoin( + "PREFIX slv2predicate: <", predicate, ">", + "SELECT DISTINCT ?value WHERE { \n" + "<> slv2predicate: ?value \n" + "}\n", NULL); + } else { + query = slv2_strjoin( + "SELECT DISTINCT ?value WHERE { \n" + "<> ", predicate, " ?value \n" + "}\n", NULL); + } SLV2Values result = slv2_plugin_simple_query(p, query, 0); @@ -360,15 +373,32 @@ slv2_plugin_get_value(SLV2Plugin p, SLV2Values slv2_plugin_get_value_for_subject(SLV2Plugin p, - const char* subject, + SLV2Value subject, + SLV2URIType predicate_type, const char* predicate) { - assert(predicate); + if (subject->type != SLV2_VALUE_URI) { + fprintf(stderr, "slv2_plugin_get_value_for_subject error: " + "passed non-URI subject\n"); + return NULL; + } + + char* query = NULL; + + /* Hack around broken RASQAL, full URI predicates don't work :/ */ - char* query = slv2_strjoin( - "SELECT DISTINCT ?value WHERE {\n", - subject, " ", predicate, " ?value .\n" - "}\n", NULL); + if (predicate_type == SLV2_URI) { + query = slv2_strjoin( + "PREFIX slv2predicate: <", predicate, ">", + "SELECT DISTINCT ?value WHERE { \n", + slv2_value_get_turtle_token(subject), " slv2predicate: ?value \n" + "}\n", NULL); + } else { + query = slv2_strjoin( + "SELECT DISTINCT ?value WHERE { \n", + slv2_value_get_turtle_token(subject), " ", predicate, " ?value \n" + "}\n", NULL); + } SLV2Values result = slv2_plugin_simple_query(p, query, 0); @@ -381,14 +411,14 @@ slv2_plugin_get_value_for_subject(SLV2Plugin p, SLV2Values slv2_plugin_get_properties(SLV2Plugin p) { - return slv2_plugin_get_value(p, "lv2:pluginProperty"); + return slv2_plugin_get_value(p, SLV2_QNAME, "lv2:pluginProperty"); } SLV2Values slv2_plugin_get_hints(SLV2Plugin p) { - return slv2_plugin_get_value(p, "lv2:pluginHint"); + return slv2_plugin_get_value(p, SLV2_QNAME, "lv2:pluginHint"); } @@ -462,7 +492,7 @@ slv2_plugin_get_optional_features(SLV2Plugin p) { const char* const query = "SELECT DISTINCT ?feature WHERE {\n" - " <> lv2:optionalHostFeature ?feature .\n" + " <> lv2:optionalHostFeature ?feature\n" "}\n"; SLV2Values result = slv2_plugin_simple_query(p, query, 0); @@ -476,7 +506,7 @@ slv2_plugin_get_required_features(SLV2Plugin p) { const char* const query = "SELECT DISTINCT ?feature WHERE {\n" - " <> lv2:requiredHostFeature ?feature .\n" + " <> lv2:requiredHostFeature ?feature\n" "}\n"; SLV2Values result = slv2_plugin_simple_query(p, query, 0); diff --git a/src/pluginclass.c b/src/pluginclass.c index 8aa4abb..6a71680 100644 --- a/src/pluginclass.c +++ b/src/pluginclass.c @@ -27,7 +27,7 @@ SLV2PluginClass slv2_plugin_class_new(SLV2World world, const char* parent_uri, const char* uri, const char* label) { - SLV2PluginClass plugin_class = (SLV2PluginClass)malloc(sizeof(struct _PluginClass)); + SLV2PluginClass plugin_class = (SLV2PluginClass)malloc(sizeof(struct _SLV2PluginClass)); plugin_class->world = world; if (parent_uri) plugin_class->parent_uri = strdup(parent_uri); diff --git a/src/pluginclasses.c b/src/pluginclasses.c index c7873fe..cac944c 100644 --- a/src/pluginclasses.c +++ b/src/pluginclasses.c @@ -21,9 +21,10 @@ #include #include #include +#include "slv2_internal.h" #include #include -#include "slv2_internal.h" + SLV2PluginClasses diff --git a/src/port.c b/src/port.c index 635b4b6..b229806 100644 --- a/src/port.c +++ b/src/port.c @@ -33,7 +33,7 @@ SLV2Port slv2_port_new(uint32_t index, const char* symbol/*, const char* node_id*/) { - struct _Port* port = malloc(sizeof(struct _Port)); + struct _SLV2Port* port = malloc(sizeof(struct _SLV2Port)); port->index = index; port->symbol = strdup(symbol); //port->node_id = strdup(node_id); @@ -55,7 +55,7 @@ slv2_port_free(SLV2Port port) SLV2Port slv2_port_duplicate(SLV2Port port) { - struct _Port* result = malloc(sizeof(struct _Port)); + SLV2Port result = malloc(sizeof(struct _SLV2Port)); result->index = port->index; result->symbol = strdup(port->symbol); //result->node_id = strdup(port->node_id); diff --git a/src/slv2_internal.h b/src/slv2_internal.h index dba9832..97fbbce 100644 --- a/src/slv2_internal.h +++ b/src/slv2_internal.h @@ -16,8 +16,8 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __SLV2_PRIVATE_TYPES_H__ -#define __SLV2_PRIVATE_TYPES_H__ +#ifndef __SLV2_INTERNAL_H__ +#define __SLV2_INTERNAL_H__ #ifdef __cplusplus extern "C" { @@ -25,15 +25,14 @@ extern "C" { #include #include +#include #include -#include -#include - +#include /** Reference to a port on some plugin. */ -struct _Port { +struct _SLV2Port { uint32_t index; ///< LV2 index char* symbol; ///< LV2 symbol //char* node_id; ///< RDF Node ID @@ -50,8 +49,8 @@ void slv2_port_free(SLV2Port port); * A simple reference to a plugin somewhere on the system. This just holds * paths of relevant files, the actual data therein isn't loaded into memory. */ -struct _Plugin { - struct _World* world; +struct _SLV2Plugin { + struct _SLV2World* world; librdf_uri* plugin_uri; // char* bundle_url; // Bundle directory plugin was loaded from char* binary_uri; // lv2:binary @@ -84,11 +83,11 @@ struct _InstanceImpl { }; -struct _PluginClass { - struct _World* world; - char* parent_uri; - char* uri; - char* label; +struct _SLV2PluginClass { + struct _SLV2World* world; + char* parent_uri; + char* uri; + char* label; }; SLV2PluginClass slv2_plugin_class_new(SLV2World world, @@ -100,7 +99,7 @@ void slv2_plugin_classes_free(); /** Model of LV2 (RDF) data loaded from bundles. */ -struct _World { +struct _SLV2World { librdf_world* world; librdf_storage* storage; librdf_model* model; @@ -123,14 +122,15 @@ slv2_world_load_path(SLV2World world, const char* search_path); -typedef enum _ValueType { +typedef enum _SLV2ValueType { SLV2_VALUE_URI, + SLV2_VALUE_QNAME, SLV2_VALUE_STRING, SLV2_VALUE_INT, SLV2_VALUE_FLOAT } SLV2ValueType; -struct _Value { +struct _SLV2Value { SLV2ValueType type; char* str_val; ///< always present union { @@ -147,5 +147,5 @@ void slv2_value_free(SLV2Value val); } #endif -#endif /* __SLV2_PRIVATE_TYPES_H__ */ +#endif /* __SLV2_INTERNAL_H__ */ diff --git a/src/value.c b/src/value.c index 1d7ead0..8911619 100644 --- a/src/value.c +++ b/src/value.c @@ -30,7 +30,7 @@ SLV2Value slv2_value_new(SLV2ValueType type, const char* str) { - SLV2Value val = (SLV2Value)malloc(sizeof(struct _Value)); + SLV2Value val = (SLV2Value)malloc(sizeof(struct _SLV2Value)); val->str_val = strdup(str); val->type = type; @@ -59,6 +59,27 @@ slv2_value_free(SLV2Value val) } +/* +SLV2Value +slv2_uri(const char* uri) +{ + struct _SLV2Value val; + val->str_val = (char*)uri; // const cast FTW! + val->type = SLV2_VALUE_URI; + return val; +} + + +SLV2Value +slv2_qname(const char* qname) +{ + SLV2Value val; + val->str_val = (char*)qname; // const cast FTW! + val->type = SLV2_VALUE_QNAME; + return val; +} +*/ + bool slv2_value_equals(SLV2Value value, SLV2Value other) { @@ -69,6 +90,39 @@ slv2_value_equals(SLV2Value value, SLV2Value other) } +char* +slv2_value_get_turtle_token(SLV2Value value) +{ + size_t len = 0; + char* result = NULL; + + switch (value->type) { + case SLV2_VALUE_URI: + len = strlen(value->str_val) + 3; + result = calloc(len, sizeof(char)); + snprintf(result, len, "<%s>", value->str_val); + break; + case SLV2_VALUE_QNAME: + case SLV2_VALUE_STRING: + result = strdup(value->str_val); + break; + case SLV2_VALUE_INT: + // INT64_MAX is 9223372036854775807 (19 digits) + 1 for sign + len = 20; + result = calloc(len, sizeof(char)); + snprintf(result, len, "%d", value->val.int_val); + break; + case SLV2_VALUE_FLOAT: + len = 20; // FIXME: proper maximum value? + result = calloc(len, sizeof(char)); + snprintf(result, len, ".1%f", value->val.float_val); + break; + } + + return result; +} + + bool slv2_value_is_uri(SLV2Value value) { @@ -102,7 +156,6 @@ slv2_value_is_string(SLV2Value value) const char* slv2_value_as_string(SLV2Value value) { - assert(slv2_value_is_string(value)); return value->str_val; } diff --git a/src/world.c b/src/world.c index dab7532..ff91ead 100644 --- a/src/world.c +++ b/src/world.c @@ -32,7 +32,7 @@ SLV2World slv2_world_new() { - struct _World* world = (struct _World*)malloc(sizeof(struct _World)); + SLV2World world = (SLV2World)malloc(sizeof(struct _SLV2World)); world->world = librdf_new_world(); librdf_world_open(world->world); @@ -60,7 +60,7 @@ slv2_world_new() SLV2World slv2_world_new_using_rdf_world(librdf_world* rdf_world) { - struct _World* world = (struct _World*)malloc(sizeof(struct _World)); + SLV2World world = (SLV2World)malloc(sizeof(struct _SLV2World)); world->world = rdf_world; diff --git a/utils/lv2_inspect.c b/utils/lv2_inspect.c index 5e45159..11f14dd 100644 --- a/utils/lv2_inspect.c +++ b/utils/lv2_inspect.c @@ -109,7 +109,26 @@ print_plugin(SLV2Plugin p) printf("\tBinary: %s\n\n", slv2_plugin_get_library_uri(p)); - printf("\tData URIs:\n"); + SLV2Values gui = slv2_plugin_get_value(p, SLV2_URI, + "http://ll-plugins.nongnu.org/lv2/ext/gtk2gui#gui"); + if (slv2_values_size(gui) > 0) { + printf("\tGUI:\n"); + for (unsigned i=0; i < slv2_values_size(gui); ++i) { + printf("\t\t%s\n", slv2_value_as_string(slv2_values_get_at(gui, i))); + SLV2Values binary = slv2_plugin_get_value_for_subject(p, + slv2_values_get_at(gui, i), + SLV2_URI, + "http://ll-plugins.nongnu.org/lv2/ext/gtk2gui#binary"); + + if (slv2_values_size(binary) > 0) + printf("\t\t\tBinary: %s\n", slv2_value_as_uri(slv2_values_get_at(binary, 0))); + } + } + + //SLV2Values gui = slv2_plugin_get_value_for_subject(p, + // ""); + + printf("\n\tData URIs:\n"); SLV2Values data_uris = slv2_plugin_get_data_uris(p); for (unsigned i=0; i < slv2_values_size(data_uris); ++i) printf("\t\t%s\n", slv2_value_as_uri(slv2_values_get_at(data_uris, i))); -- cgit v1.2.1