summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-05-08 03:30:37 +0000
committerDavid Robillard <d@drobilla.net>2007-05-08 03:30:37 +0000
commitf6ff6e487201bdd94e584397ce829daaa424aba9 (patch)
treeaedf571fe2c1db5d3d3cd1511805e51aca64a75e
parent816279720d70902bf1beba5a2aaaf135707ae77f (diff)
downloadlilv-f6ff6e487201bdd94e584397ce829daaa424aba9.tar.gz
lilv-f6ff6e487201bdd94e584397ce829daaa424aba9.tar.bz2
lilv-f6ff6e487201bdd94e584397ce829daaa424aba9.zip
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
-rw-r--r--slv2/plugin.h10
-rw-r--r--slv2/plugins.h4
-rw-r--r--slv2/types.h27
-rw-r--r--slv2/value.h63
-rw-r--r--src/plugin.c66
-rw-r--r--src/pluginclass.c2
-rw-r--r--src/pluginclasses.c3
-rw-r--r--src/port.c4
-rw-r--r--src/slv2_internal.h34
-rw-r--r--src/value.c57
-rw-r--r--src/world.c4
-rw-r--r--utils/lv2_inspect.c21
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 <slv2/types.h>
#include <slv2/plugin.h>
#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:
+ * <http://example.org/foo>
+ * 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 <stdlib.h>
#include <assert.h>
#include <librdf.h>
+#include "slv2_internal.h"
#include <slv2/plugin.h>
#include <slv2/types.h>
#include <slv2/util.h>
#include <slv2/values.h>
-#include "slv2_internal.h"
+#include <slv2/pluginclass.h>
+#include <slv2/pluginclasses.h>
/* 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 <string.h>
#include <limits.h>
#include <librdf.h>
+#include "slv2_internal.h"
#include <slv2/pluginclass.h>
#include <slv2/pluginclasses.h>
-#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 <stdbool.h>
#include <stddef.h>
+#include <inttypes.h>
#include <librdf.h>
-#include <slv2/plugins.h>
-#include <slv2/pluginclasses.h>
-
+#include <slv2/types.h>
/** 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,
+ // "<http://ll-plugins.nongnu.org/lv2/ext/gtk2gui#gui>");
+
+ 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)));