1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-29 15:09:30 +02:00
2010-01-24 09:19:39 +00:00

1332 lines
32 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <raptor.h>
#include <ladspa.h>
#include <time.h>
#include <sys/types.h>
#if !defined(WIN32)
#include <unistd.h>
#include <sys/time.h>
#endif
#include "lrdf.h"
#include "lrdf_md5.h"
/* XXX The size if that hash table, should be dyunamic, but this will do for
* now */
#define LRDF_HASH_SIZE 1024
static unsigned int lrdf_uid = 0; /* A unique(ish) id to append to genid's to
* avoid clashses */
static lrdf_statement *triples = NULL;
static lrdf_statement *free_triples;
static lrdf_string_hash *resources_hash[LRDF_HASH_SIZE];
static lrdf_string_hash *literals_hash[LRDF_HASH_SIZE];
static lrdf_triple_hash *subj_hash[LRDF_HASH_SIZE];
static lrdf_triple_hash *obj_hash[LRDF_HASH_SIZE];
static lrdf_triple_hash *pred_hash[LRDF_HASH_SIZE];
static lrdf_closure_hash *subclass_hash[LRDF_HASH_SIZE];
static lrdf_closure_hash *superclass_hash[LRDF_HASH_SIZE];
static lrdf_hash rdf_resource_h;
/* Internal functions */
void lrdf_more_triples(int count);
lrdf_statement *lrdf_alloc_statement();
lrdf_statement *lrdf_all_triples();
static char *lrdf_check_hash(lrdf_string_hash ** tbl, lrdf_hash hash, const char
*str);
static char *lrdf_find_string_hash(lrdf_string_hash ** tbl,
lrdf_hash hash);
static void lrdf_add_triple_hash(lrdf_triple_hash ** tbl, lrdf_hash hash,
lrdf_statement * s);
static void lrdf_remove_triple_hash(lrdf_triple_hash ** tbl,
lrdf_hash hash, lrdf_statement * s);
static void lrdf_add_closure_hash(lrdf_closure_hash ** tbl,
lrdf_hash subject, lrdf_hash object);
static void lrdf_store(void *user_data,
const raptor_statement * statement);
void lrdf_free_statements(lrdf_statement * s);
void lrdf_copy_statement(lrdf_statement * from, lrdf_statement * to);
void lrdf_rebuild_taxonomic_closure(lrdf_closure_hash ** fwd_tbl,
lrdf_closure_hash ** rev_tbl);
static lrdf_uris *lrdf_uris_new(int size);
int lrdf_read_file_intl(const char *uri);
static void lrdf_uris_append(lrdf_uris * base, lrdf_uris * add);
static inline lrdf_hash lrdf_gen_hash(const char *str);
void lrdf_free_string_hash(lrdf_string_hash * h[]);
void lrdf_free_triple_hash(lrdf_triple_hash * h[]);
void lrdf_free_closure_hash(lrdf_closure_hash * h[]);
static inline lrdf_hash lrdf_gen_hash(const char *str)
{
lrdf_hash data[2];
md5_buffer(str, strlen(str), data);
return data[0];
}
void lrdf_init()
{
unsigned int i;
struct timeval tv;
raptor_init();
lrdf_more_triples(256);
/* A UID to add to genids to make them safer */
gettimeofday(&tv, NULL);
lrdf_uid = (unsigned int) getpid();
lrdf_uid ^= (unsigned int) tv.tv_usec;
/* Global value for the hash of rdf:Resource, saves time */
rdf_resource_h = lrdf_gen_hash(RDF_RESOURCE);
/* Make sure all the hashes are empty, just incase */
for (i = 0; i < LRDF_HASH_SIZE; i++) {
resources_hash[i] = NULL;
literals_hash[i] = NULL;
subj_hash[i] = NULL;
obj_hash[i] = NULL;
pred_hash[i] = NULL;
subclass_hash[i] = NULL;
superclass_hash[i] = NULL;
}
/* Make sure we have rdf:Resource in our hash tables */
lrdf_check_hash(resources_hash, rdf_resource_h, RDF_RESOURCE);
}
void lrdf_more_triples(int count)
{
int i;
lrdf_statement *new;
new = (lrdf_statement *) calloc(count, sizeof(lrdf_statement));
for (i = 0; i < count - 1; i++) {
new[i].next = new + i + 1;
}
new[count - 1].next = free_triples;
free_triples = new;
}
void lrdf_cleanup()
{
raptor_finish();
lrdf_free_string_hash(resources_hash);
lrdf_free_string_hash(literals_hash);
lrdf_free_triple_hash(subj_hash);
lrdf_free_triple_hash(obj_hash);
lrdf_free_triple_hash(pred_hash);
lrdf_free_closure_hash(subclass_hash);
lrdf_free_closure_hash(superclass_hash);
}
lrdf_statement *lrdf_alloc_statement()
{
lrdf_statement *s;
if (free_triples == NULL) {
lrdf_more_triples(256);
}
s = free_triples;
free_triples = free_triples->next;
s->next = NULL;
return s;
}
void lrdf_free_statements(lrdf_statement * s)
{
lrdf_statement *next;
for (; s != NULL; s = next) {
next = s->next;
s->next = free_triples;
free_triples = s;
}
}
void lrdf_add_triple(const char *source, const char *subject, const char
*predicate, const char *object,
enum lrdf_objtype literal)
{
lrdf_statement *s = lrdf_alloc_statement();
s->shash = lrdf_gen_hash(subject);
s->phash = lrdf_gen_hash(predicate);
s->ohash = lrdf_gen_hash(object);
s->next = triples;
triples = s;
s->subject = lrdf_check_hash(resources_hash, s->shash, subject);
s->predicate = lrdf_check_hash(resources_hash, s->phash, predicate);
if (literal == lrdf_literal) {
s->object = lrdf_check_hash(literals_hash, s->ohash, object);
s->object_type = lrdf_literal;
} else {
s->object = lrdf_check_hash(resources_hash, s->ohash, object);
s->object_type = lrdf_uri;
}
lrdf_add_triple_hash(subj_hash, s->shash, s);
lrdf_add_triple_hash(obj_hash, s->ohash, s);
lrdf_add_triple_hash(pred_hash, s->phash, s);
if (source) {
s->source = lrdf_gen_hash(source);
} else {
s->source = 0;
}
}
void lrdf_remove_uri_matches(const char *uri)
{
lrdf_statement p;
p.subject = (char *)uri;
p.predicate = NULL;
p.object = NULL;
lrdf_remove_matches(&p);
p.subject = NULL;
p.predicate = (char *)uri;
lrdf_remove_matches(&p);
p.predicate = NULL;
p.object = (char *)uri;
lrdf_remove_matches(&p);
/* we could also remove the hash of the uri from the lookup tables, but we
* don't. natch */
}
void lrdf_remove_matches(lrdf_statement *pattern)
{
lrdf_statement *s;
lrdf_statement *it;
while ((s = lrdf_one_match(pattern))) {
/* If the head triple is the one we want to remove */
if (triples == s) {
triples = s->next;
lrdf_remove_triple_hash(subj_hash, s->shash, s);
lrdf_remove_triple_hash(pred_hash, s->phash, s);
lrdf_remove_triple_hash(obj_hash, s->ohash, s);
s->next = NULL;
lrdf_free_statements(s);
continue;
}
/* Else its somwehere in the tail of the list */
for (it = triples; it; it = it->next) {
if (it->next == s) {
it->next = it->next->next;
lrdf_remove_triple_hash(subj_hash, s->shash, s);
lrdf_remove_triple_hash(pred_hash, s->phash, s);
lrdf_remove_triple_hash(obj_hash, s->ohash, s);
s->next = NULL;
lrdf_free_statements(s);
break;
}
}
}
}
static void lrdf_store(void *user_data, const raptor_statement * statement)
{
lrdf_statement *s = lrdf_alloc_statement();
char tmps[128], tmpp[128], tmpo[128];
char *subj = (char *) statement->subject,
*pred = (char *) statement->predicate,
*obj = (char *) statement->object;
if (statement->subject_type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS) {
snprintf(tmps, 127, "_:%s.%x", subj, lrdf_uid);
subj = tmps;
}
if (statement->predicate_type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS) {
snprintf(tmpp, 127, "_:%s.%x", pred, lrdf_uid);
pred = tmpp;
}
if (statement->object_type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS) {
snprintf(tmpo, 127, "_:%s.%x", obj, lrdf_uid);
obj = tmpo;
}
s->shash = lrdf_gen_hash(subj);
s->phash = lrdf_gen_hash(pred);
s->ohash = lrdf_gen_hash(obj);
s->next = triples;
triples = s;
s->subject = lrdf_check_hash(resources_hash, s->shash, subj);
s->predicate = lrdf_check_hash(resources_hash, s->phash, pred);
if (statement->object_type == RAPTOR_IDENTIFIER_TYPE_LITERAL) {
s->object = lrdf_check_hash(literals_hash, s->ohash, obj);
s->object_type = lrdf_literal;
} else {
s->object = lrdf_check_hash(resources_hash, s->ohash, obj);
s->object_type = lrdf_uri;
}
lrdf_add_triple_hash(subj_hash, s->shash, s);
lrdf_add_triple_hash(obj_hash, s->ohash, s);
lrdf_add_triple_hash(pred_hash, s->phash, s);
s->source = *((lrdf_hash *) user_data);
}
static char *lrdf_check_hash(lrdf_string_hash ** tbl, lrdf_hash hash, const char
*str)
{
lrdf_string_hash *tmp, *newe;
char *tmps, *newstr;
if ((tmps = lrdf_find_string_hash(tbl, hash))) {
return tmps;
} else {
tmp = tbl[hash & (LRDF_HASH_SIZE - 1)];
newstr = strdup(str);
newe = (lrdf_string_hash *) malloc(sizeof(lrdf_string_hash));
newe->hash = hash;
newe->str = newstr;
newe->next = tmp;
tbl[hash & (LRDF_HASH_SIZE - 1)] = newe;
return newstr;
}
}
static char *lrdf_find_string_hash(lrdf_string_hash ** tbl, lrdf_hash hash)
{
lrdf_string_hash *p = tbl[hash & (LRDF_HASH_SIZE - 1)];
while (p) {
if (p->hash == hash) {
return p->str;
}
p = p->next;
}
return NULL;
}
static void lrdf_add_triple_hash(lrdf_triple_hash ** tbl, lrdf_hash hash,
lrdf_statement * s)
{
lrdf_triple_hash *p = tbl[hash & (LRDF_HASH_SIZE - 1)];
lrdf_triple_hash *newe = malloc(sizeof(lrdf_triple_hash));
newe->hash = hash;
newe->triple = s;
newe->next = p;
tbl[hash & (LRDF_HASH_SIZE - 1)] = newe;
}
static void lrdf_remove_triple_hash(lrdf_triple_hash ** tbl,
lrdf_hash hash, lrdf_statement * s)
{
lrdf_triple_hash *p = tbl[hash & (LRDF_HASH_SIZE - 1)];
lrdf_triple_hash *it;
/* The entry we want to remove is the first */
if (p && p->triple == s) {
it = p->next;
free(p);
tbl[hash & (LRDF_HASH_SIZE - 1)] = it;
return;
}
/* The entry is somewhere in the list */
for (it = p; it; it = it->next) {
if (it->next && it->next->triple == s) {
p = it->next;
it->next = it->next->next;
free(p);
return;
}
}
fprintf(stderr,
"lrdf: tried to remove non-existant triple hash %llx\n", hash);
}
static void lrdf_add_closure_hash(lrdf_closure_hash ** tbl,
lrdf_hash subject, lrdf_hash object)
{
lrdf_closure_hash *p = tbl[subject & (LRDF_HASH_SIZE - 1)];
lrdf_closure_hash *newe = malloc(sizeof(lrdf_closure_hash));
newe->subject = subject;
newe->object = object;
newe->next = p;
tbl[subject & (LRDF_HASH_SIZE - 1)] = newe;
}
int lrdf_export_by_source(const char *src, const char *file)
{
lrdf_hash source = lrdf_gen_hash(src);
lrdf_statement *s;
const char *outfile = file;
FILE *out;
if (!strncasecmp(file, "file:", 5)) {
outfile = file + 5;
}
if (!(out = fopen(outfile, "w"))) {
fprintf(stderr, "lrdf: trying to write '%s'\n", outfile);
perror("");
return -1;
}
for (s = triples; s; s = s->next) {
if (s->source == source) {
if (s->object_type == lrdf_uri) {
fprintf(out, "<%s> <%s> <%s> .\n", s->subject,
s->predicate, s->object);
} else {
fprintf(out, "<%s> <%s> \"%s\" .\n",
s->subject, s->predicate, s->object);
}
}
}
fclose(out);
return 0;
}
void lrdf_rebuild_caches()
{
lrdf_rebuild_taxonomic_closure(subclass_hash, superclass_hash);
}
void lrdf_rebuild_taxonomic_closure(lrdf_closure_hash ** fwd_tbl,
lrdf_closure_hash ** rev_tbl)
{
lrdf_string_hash *tmp[LRDF_HASH_SIZE];
lrdf_string_hash *hit;
char **uris;
int *pathto;
lrdf_statement q;
lrdf_statement *m;
lrdf_statement *it;
unsigned int class_count = 0;
unsigned int i, j, k;
/* Ensure the tmp table is cleared out */
for (i = 0; i < LRDF_HASH_SIZE; i++) {
tmp[i] = NULL;
}
/* Find all explicitly named classes */
q.subject = NULL;
q.predicate = RDF_TYPE;
q.object = RDFS_CLASS;
m = lrdf_matches(&q);
for (it = m; it; it = it->next) {
lrdf_check_hash(tmp, it->shash, it->subject);
}
lrdf_free_statements(m);
/* Find all implicitly name classes */
q.subject = NULL;
q.predicate = RDFS_SUBCLASSOF;
q.object = NULL;
m = lrdf_matches(&q);
for (it = m; it != NULL; it = it->next) {
lrdf_check_hash(tmp, it->shash, it->subject);
lrdf_check_hash(tmp, it->ohash, it->object);
}
/* Count unique class uris */
for (i = 0; i < LRDF_HASH_SIZE; i++) {
for (hit = tmp[i]; hit; hit = hit->next) {
class_count++;
}
}
uris = malloc(class_count * sizeof(char *));
class_count = 0;
for (i = 0; i < LRDF_HASH_SIZE; i++) {
for (hit = tmp[i]; hit; hit = hit->next) {
uris[class_count] = hit->str;
hit->str = (char *) class_count++;
}
}
pathto = calloc(class_count * class_count, sizeof(int));
for (it = m; it != NULL; it = it->next) {
/* The subclass is the matrix column */
int c = (int) lrdf_find_string_hash(tmp, it->shash);
/* And the superclass is the row */
int r = (int) lrdf_find_string_hash(tmp, it->ohash);
pathto[c + class_count * r] = 1;
}
lrdf_free_statements(m);
/* Warshall's algorithm
*
* $adjacent[X][Z] and $adjacent[Z][Y] => $adjacent[X][Y]
*/
for (k = 0; k < class_count; k++) {
for (i = 0; i < class_count; i++) {
for (j = 0; j < class_count; j++) {
if (pathto[i + class_count * j] != 1) {
pathto[i + class_count * j] =
pathto[i + class_count * k] &&
pathto[k + class_count * j];
}
}
}
}
/* Clear out and free the forward and reverse tables */
for (i = 0; i < LRDF_HASH_SIZE; i++) {
lrdf_closure_hash *next;
lrdf_closure_hash *hit;
for (hit = fwd_tbl[i]; hit; hit = next) {
next = hit->next;
free(hit);
}
fwd_tbl[i] = NULL;
for (hit = rev_tbl[i]; hit; hit = next) {
next = hit->next;
free(hit);
}
rev_tbl[i] = NULL;
}
for (i = 0; i < class_count; i++) {
lrdf_hash class_h = lrdf_gen_hash(uris[i]);
lrdf_hash subclass_h;
/* Every class is a subclass of itsself */
lrdf_add_closure_hash(fwd_tbl, class_h, class_h);
lrdf_add_closure_hash(rev_tbl, class_h, class_h);
/* ...and rdf:Resource */
lrdf_add_closure_hash(fwd_tbl, rdf_resource_h, class_h);
lrdf_add_closure_hash(rev_tbl, class_h, rdf_resource_h);
for (j = 0; j < class_count; j++) {
subclass_h = lrdf_gen_hash(uris[j]);
if (pathto[j + class_count * i]) {
lrdf_add_closure_hash(fwd_tbl, class_h, subclass_h);
lrdf_add_closure_hash(rev_tbl, subclass_h, class_h);
}
}
}
for (i = 0; i < LRDF_HASH_SIZE; i++) {
lrdf_string_hash *next;
lrdf_string_hash *hit;
for (hit = tmp[i]; hit; hit = next) {
next = hit->next;
free(hit);
}
}
for (i = 0; i < class_count; i++) {
free(uris[i]);
}
free(uris);
free(pathto);
}
static void lrdf_error_handler(void *data, raptor_locator * locator,
const char *message);
static void lrdf_error_handler(void *data, raptor_locator * locator,
const char *message)
{
fprintf(stderr, "liblrdf: error - ");
raptor_print_locator(stderr, locator);
fprintf(stderr, " - %s\n", message);
raptor_parse_abort((raptor_parser*)data);
}
static void lrdf_warning_handler(void *data, raptor_locator * locator,
const char *message);
static void lrdf_warning_handler(void *data, raptor_locator * locator,
const char *message)
{
fprintf(stderr, "liblrdf: warning - ");
raptor_print_locator(stderr, locator);
fprintf(stderr, " - %s\n", message);
}
int lrdf_read_files(const char *uri[])
{
unsigned int i;
for (i = 0; uri[i] != NULL; i++) {
if (lrdf_read_file_intl(uri[i]) != 0) {
return 1;
}
}
lrdf_rebuild_caches();
return 0;
}
int lrdf_read_file(const char *uri)
{
int ret;
ret = lrdf_read_file_intl(uri);
lrdf_rebuild_caches();
return ret;
}
int lrdf_read_file_intl(const char *uri)
{
raptor_parser *parser = NULL;
raptor_uri *ruri, *furi;
lrdf_hash source;
//printf("lrdf: reading %s\n", uri);
ruri = raptor_new_uri(uri);
furi = raptor_new_uri(uri);
source = lrdf_gen_hash(uri);
lrdf_check_hash(resources_hash, source, uri);
if (strstr(uri, ".rdf")) {
parser = raptor_new_parser("rdfxml");
} else {
parser = raptor_new_parser("ntriples");
}
if (!parser) {
fprintf(stderr, "liblrdf: failed to create parser\n");
raptor_free_uri(ruri);
return 1;
}
raptor_set_error_handler(parser, parser, lrdf_error_handler);
raptor_set_warning_handler(parser, NULL, lrdf_warning_handler);
raptor_set_statement_handler(parser, &source, lrdf_store);
raptor_set_default_generate_id_parameters(parser, NULL, ++lrdf_uid);
if (raptor_parse_file(parser, furi, ruri)) {
raptor_free_uri(furi);
raptor_free_uri(ruri);
raptor_free_parser(parser);
return 1;
}
raptor_free_uri(ruri);
raptor_free_parser(parser);
return 0;
}
char *lrdf_get_default_uri(unsigned long id)
{
lrdf_statement *types;
lrdf_statement *it;
lrdf_statement type_s;
lrdf_statement plugin_s;
char *uri = NULL;
char plugin_uri[64];
snprintf(plugin_uri, 64, "http://ladspa.org/ontology#%ld", id);
type_s.subject = NULL;
type_s.predicate = RDF_TYPE;
type_s.object_type = lrdf_uri;
type_s.object = "http://ladspa.org/ontology#Default";
types = lrdf_matches(&type_s);
for (it = types; it != NULL; it = it->next) {
plugin_s.subject = plugin_uri;
plugin_s.predicate = LADSPA_BASE "hasSetting";
plugin_s.object = it->subject;
if (lrdf_exists_match(&plugin_s)) {
uri = it->subject;
break;
}
}
lrdf_free_statements(types);
return uri;
}
lrdf_uris *lrdf_get_setting_uris(unsigned long id)
{
lrdf_statement *settings;
lrdf_statement *it;
lrdf_statement plugin_s;
lrdf_uris *ret;
char **uris;
char plugin_uri[64];
int scnt = 0;
snprintf(plugin_uri, 64, "http://ladspa.org/ontology#%ld", id);
plugin_s.subject = plugin_uri;
plugin_s.predicate = LADSPA_BASE "hasSetting";
plugin_s.object = NULL;
settings = lrdf_matches(&plugin_s);
for (it = settings; it != NULL; it = it->next) {
scnt++;
}
ret = malloc(sizeof(lrdf_uris));
uris = (char **) calloc(scnt + 1, sizeof(char **));
ret->items = uris;
for (it = settings, scnt = 0; it != NULL; it = it->next) {
uris[scnt++] = it->object;
}
lrdf_free_statements(settings);
ret->count = scnt;
return ret;
}
lrdf_defaults *lrdf_get_setting_values(const char *uri)
{
lrdf_statement *portvalues;
lrdf_statement *it;
lrdf_statement *port;
lrdf_statement portv_s;
lrdf_statement port_s;
lrdf_defaults *ret;
lrdf_portvalue *list;
int pvcount = 0;
char *pos;
char *port_uri;
if (!uri) {
return NULL;
}
/* Find portvalues associated with setting URI */
portv_s.subject = (char *)uri;
portv_s.predicate = LADSPA_BASE "hasPortValue";
portv_s.object = NULL;
portvalues = lrdf_matches(&portv_s);
for (it = portvalues; it != NULL; it = it->next) {
pvcount++;
}
if (pvcount == 0) {
return NULL;
}
ret = (lrdf_defaults *) calloc(1, sizeof(lrdf_defaults));
list = (lrdf_portvalue *) calloc(pvcount, sizeof(lrdf_portvalue));
ret->count = pvcount;
ret->items = list;
for (it = portvalues, pvcount = 0; it != NULL;
it = it->next, pvcount++) {
/* Find setting's port */
port_s.subject = it->object;
port_s.predicate = LADSPA_BASE "forPort";
port_s.object = NULL;
port = lrdf_one_match(&port_s);
if (port != NULL) {
port_uri = port->object;
pos = strrchr(port_uri, '.');
list[pvcount].pid = atoi(pos + 1);
/* Find port's set value */
port_s.predicate = RDF_BASE "value";
port = lrdf_one_match(&port_s);
if (port != NULL) {
list[pvcount].value = atof(port->object);
}
/* Find port's short name */
port_s.subject = port_uri;
port_s.predicate = LADSPA_BASE "hasLabel";
port_s.object = NULL;
port = lrdf_one_match(&port_s);
if (port != NULL && port->object != NULL) {
list[pvcount].label = port->object;
}
}
}
return ret;
}
lrdf_defaults *lrdf_get_scale_values(unsigned long id, unsigned long port)
{
char port_uri[128];
lrdf_statement scale_p;
lrdf_statement *scale_s;
char *scale_uri;
lrdf_statement p1;
lrdf_uris *ulist;
lrdf_defaults *ret;
lrdf_portvalue *list;
int i;
snprintf(port_uri, 127, LADSPA_BASE "%ld.%ld", id, port);
/* Find Scale associated with port */
scale_p.subject = port_uri;
scale_p.predicate = LADSPA_BASE "hasScale";
scale_p.object = NULL;
scale_s = lrdf_matches(&scale_p);
if (!scale_s) {
return NULL;
}
scale_uri = scale_s->object;
p1.subject = scale_uri;
p1.predicate = LADSPA_BASE "hasPoint";
p1.object = "?";
p1.next = NULL;
ulist = lrdf_match_multi(&p1);
if (!ulist) {
return NULL;
}
ret = (lrdf_defaults *) calloc(1, sizeof(lrdf_defaults));
list = (lrdf_portvalue *) calloc(ulist->count, sizeof(lrdf_portvalue));
ret->count = ulist->count;
ret->items = list;
for (i=0; i < ulist->count; i++) {
list[i].pid = port;
scale_p.subject = ulist->items[i];
scale_p.predicate = RDF_BASE "value";
scale_p.object = NULL;
scale_s = lrdf_one_match(&scale_p);
list[i].value = atof(scale_s->object);
scale_p.predicate = LADSPA_BASE "hasLabel";
scale_s = lrdf_one_match(&scale_p);
list[i].label = scale_s->object;
}
return ret;
}
void lrdf_free_setting_values(lrdf_defaults * def)
{
if (def) {
free(def->items);
free(def);
}
}
char *lrdf_get_setting_metadata(const char *uri, const char *element)
{
lrdf_statement meta_s;
lrdf_statement *m;
char dc_uri[128];
snprintf(dc_uri, 128, DC_BASE "%s", element);
meta_s.subject = (char *)uri;
meta_s.predicate = dc_uri;
meta_s.object = NULL;
m = lrdf_one_match(&meta_s);
if (m) {
return m->object;
}
return NULL;
}
/* lrdf_free_uris:
*
* Called on the return values from lrdf_get_subclasses etc. to free up the
* memory allocated by them.
*/
void lrdf_free_uris(lrdf_uris * u)
{
if (u) {
free(u->items);
free(u);
}
}
static lrdf_uris *lrdf_uris_new(int size)
{
lrdf_uris *nu;
nu = malloc(sizeof(lrdf_uris));
nu->items = malloc(size * sizeof(char *));
nu->size = size;
nu->count = 0;
return nu;
}
static void lrdf_uris_append(lrdf_uris * base, lrdf_uris * add)
{
unsigned int i;
if (!add) {
return;
}
if (base->count + add->count > base->size) {
base->size *= 2;
base->items = realloc(base->items, base->size);
}
for (i = 0; i < add->count; i++) {
base->items[i + base->count] = add->items[i];
}
base->count += add->count;
}
/* lrdf_get_subclasses
*
* Returns a list of the direct subclasses of a given class
*/
lrdf_uris *lrdf_get_subclasses(const char *uri)
{
lrdf_statement sc_s;
lrdf_statement *m;
lrdf_statement *it;
lrdf_uris *ret;
char **uris;
int count = 0;
ret = malloc(sizeof(lrdf_uris));
uris = malloc(256 * sizeof(char *));
ret->items = uris;
sc_s.subject = NULL;
sc_s.predicate = RDFS_BASE "subClassOf";
sc_s.object = (char *)uri;
m = lrdf_matches(&sc_s);
if (m == NULL) {
free(ret);
free(uris);
return NULL;
}
for (it = m; it != NULL; it = it->next) {
uris[count++] = it->subject;
}
lrdf_free_statements(m);
ret->count = count;
return ret;
}
/* lrdf_get_all_subclasses:
*
* Returns a list of all the subclasses of uri
*/
lrdf_uris *lrdf_get_all_subclasses(const char *uri)
{
lrdf_uris *ret;
lrdf_closure_hash *ch;
lrdf_closure_hash *hit;
lrdf_hash class;
int count = 0;
ret = malloc(sizeof(lrdf_uris));
class = lrdf_gen_hash(uri);
ch = subclass_hash[class & (LRDF_HASH_SIZE - 1)];
for (hit = ch; hit; hit = hit->next) {
if (class == hit->subject) {
count++;
}
}
if (count == 0) {
return NULL;
}
ret = lrdf_uris_new(count);
ret->count = count;
count = 0;
for (hit = ch; hit; hit = hit->next) {
if (class == hit->subject) {
ret->items[count++] =
lrdf_find_string_hash(resources_hash, hit->object);
}
}
return ret;
}
/* lrdf_get_all_superclasses:
*
* Returns a list of all the superlasses of uri
*/
lrdf_uris *lrdf_get_all_superclasses(const char *uri)
{
lrdf_uris *ret;
lrdf_closure_hash *ch;
lrdf_closure_hash *hit;
lrdf_hash class;
int count = 0;
ret = malloc(sizeof(lrdf_uris));
class = lrdf_gen_hash(uri);
ch = superclass_hash[class & (LRDF_HASH_SIZE - 1)];
for (hit = ch; hit; hit = hit->next) {
if (class == hit->subject) {
count++;
}
}
if (count == 0) {
return NULL;
}
ret = lrdf_uris_new(count);
ret->count = count;
count = 0;
for (hit = ch; hit; hit = hit->next) {
if (class == hit->subject) {
ret->items[count++] =
lrdf_find_string_hash(resources_hash, hit->object);
}
}
return ret;
}
/* lrdf_get_instances
*
* Returns a list of the instances of a given class
*/
lrdf_uris *lrdf_get_instances(const char *uri)
{
lrdf_statement inst_s;
lrdf_statement *m;
lrdf_statement *it;
lrdf_uris *ret;
char **uris;
int count = 0;
ret = lrdf_uris_new(256);
uris = ret->items;
inst_s.subject = NULL;
inst_s.predicate = RDF_BASE "type";
inst_s.object = (char *)uri;
m = lrdf_matches(&inst_s);
if (m == NULL) {
free(ret);
free(uris);
return NULL;
}
for (it = m; it != NULL; it = it->next) {
uris[count++] = it->subject;
}
lrdf_free_statements(m);
ret->count = count;
return ret;
}
/* lrdf_get_all_instances:
*
* Returns the URIs of all the instances of 'uri' and all the instances of all
* its subclasses.
*/
lrdf_uris *lrdf_get_all_instances(const char *uri)
{
unsigned int i;
lrdf_uris *u, *v;
lrdf_uris *ret = NULL;
u = lrdf_get_all_subclasses(uri);
if (u->count > 0) {
ret = lrdf_uris_new(256);
for (i = 0; i < u->count; i++) {
v = lrdf_get_instances(u->items[i]);
lrdf_uris_append(ret, v);
lrdf_free_uris(v);
}
}
return ret;
}
char *lrdf_get_label(const char *uri)
{
lrdf_statement lab_s;
lrdf_statement *label;
lab_s.subject = (char *)uri;
lab_s.predicate = LADSPA_BASE "hasLabel";
lab_s.object = NULL;
label = lrdf_one_match(&lab_s);
if (label == NULL) {
return NULL;
}
return label->object;
}
/* XXX nasty hack */
unsigned long lrdf_get_uid(const char *uri)
{
char *pos;
pos = strrchr(uri, '#');
if (pos != NULL) {
return atol(pos + 1);
}
return 0;
}
/* lrdf_matches:
*
* Returns a NULL terminated vector of lrdf_statements that match the
* sepecifed pattern, where a NULL in any position matches any uri.
*/
lrdf_statement *lrdf_matches(lrdf_statement * pattern)
{
lrdf_triple_hash *th;
lrdf_triple_hash *start;
lrdf_statement *s;
lrdf_statement *ret = NULL;
#ifdef DEBUG
printf("Looking for (%s, %s, %s)\n", pattern->subject,
pattern->predicate, pattern->object);
#endif
if (pattern->subject) {
pattern->shash = lrdf_gen_hash(pattern->subject);
}
if (pattern->predicate) {
pattern->phash = lrdf_gen_hash(pattern->predicate);
}
if (pattern->object) {
pattern->ohash = lrdf_gen_hash(pattern->object);
}
if (pattern->subject) {
start = subj_hash[pattern->shash & (LRDF_HASH_SIZE - 1)];
} else if (pattern->predicate) {
start = pred_hash[pattern->phash & (LRDF_HASH_SIZE - 1)];
} else if (pattern->object) {
start = obj_hash[pattern->ohash & (LRDF_HASH_SIZE - 1)];
} else {
/* None of the triple parts were specified, can't do anything
* useful with that, except return everything and that is
* stupid. If you want everything look thorugh the list */
fprintf(stderr, "lrdf: null triple specified for search\n");
return NULL;
}
for (th = start; th; th = th->next) {
s = th->triple;
if ((pattern->subject == NULL ||
pattern->shash == s->shash) &&
(pattern->predicate == NULL ||
pattern->phash == s->phash) &&
(pattern->object == NULL || pattern->ohash == s->ohash)) {
lrdf_statement *new = lrdf_alloc_statement();
#ifdef DEBUG
printf("Found (%s, %s, %s)\n", pattern->subject,
pattern->predicate, pattern->object);
printf(" = (%s, %s, %s)\n", s->subject, s->predicate,
s->object);
printf(" (%llx, %llx, %llx)\n", pattern->shash,
pattern->phash, pattern->ohash);
printf(" = (%llx, %llx, %llx)\n", s->shash, s->phash,
s->ohash);
#endif
lrdf_copy_statement(s, new);
new->next = ret;
ret = new;
}
}
return ret;
}
/* lrdf_one_match:
*
* returns a pointer to the first matching triple if one exists, or NULL
* otherwise
*/
lrdf_statement *lrdf_one_match(lrdf_statement *pattern)
{
lrdf_triple_hash *th;
lrdf_triple_hash *start;
lrdf_statement *s;
if (pattern->subject) {
pattern->shash = lrdf_gen_hash(pattern->subject);
}
if (pattern->predicate) {
pattern->phash = lrdf_gen_hash(pattern->predicate);
}
if (pattern->object) {
pattern->ohash = lrdf_gen_hash(pattern->object);
}
if (pattern->subject) {
start = subj_hash[pattern->shash & (LRDF_HASH_SIZE - 1)];
} else if (pattern->predicate) {
start = pred_hash[pattern->phash & (LRDF_HASH_SIZE - 1)];
} else if (pattern->object) {
start = obj_hash[pattern->ohash & (LRDF_HASH_SIZE - 1)];
} else {
/* None of the triple parts were specified, can't do anything
* useful with that, except return everything and that is
* stupid. If you want everything look thorugh the list */
fprintf(stderr, "lrdf: null triple specified for search\n");
return NULL;
}
for (th = start; th; th = th->next) {
s = th->triple;
if ((pattern->subject == NULL ||
pattern->shash == s->shash) &&
(pattern->predicate == NULL ||
pattern->phash == s->phash) &&
(pattern->object == NULL || pattern->ohash == s->ohash)) {
return s;
}
}
return NULL;
}
/* lrdf_exists_match:
*
* returns true if a triple mathcing the pattern exists, false otherwise
*/
int lrdf_exists_match(lrdf_statement *pattern)
{
return (lrdf_one_match(pattern) != NULL);
}
/* lrdf_copy_statement:
*
* copies the subject, predicate and object of a statement to another
* statement. does not affect the linked list pointer.
*/
void lrdf_copy_statement(lrdf_statement * from, lrdf_statement * to)
{
to->subject = from->subject;
to->predicate = from->predicate;
to->object = from->object;
to->object_type = from->object_type;
to->shash = from->shash;
to->phash = from->phash;
to->ohash = from->ohash;
}
void lrdf_free_string_hash(lrdf_string_hash * h[])
{
unsigned int i;
for (i = 0; i < LRDF_HASH_SIZE; i++) {
lrdf_string_hash *next;
lrdf_string_hash *hit;
for (hit = h[i]; hit; hit = next) {
next = hit->next;
free(hit->str);
free(hit);
}
}
}
void lrdf_free_triple_hash(lrdf_triple_hash * h[])
{
unsigned int i;
for (i = 0; i < LRDF_HASH_SIZE; i++) {
lrdf_triple_hash *next;
lrdf_triple_hash *hit;
for (hit = h[i]; hit; hit = next) {
next = hit->next;
free(hit);
}
}
}
void lrdf_free_closure_hash(lrdf_closure_hash * h[])
{
unsigned int i;
for (i = 0; i < LRDF_HASH_SIZE; i++) {
lrdf_closure_hash *next;
lrdf_closure_hash *hit;
for (hit = h[i]; hit; hit = next) {
next = hit->next;
free(hit);
}
}
}
lrdf_statement *lrdf_all_statements()
{
return triples;
}
char* lrdf_add_preset(const char *source, const char *label, unsigned long id,
lrdf_defaults *vals)
{
char plugin_uri[64];
char* setting_uri;
static int sid = 0;
int i;
setting_uri = malloc(64 * sizeof(char));
snprintf(plugin_uri, 64, "http://ladspa.org/ontology#%ld", id);
snprintf(setting_uri, 64, "http://plugin.org.uk/genid#%d.%d", lrdf_uid, sid++);
lrdf_add_triple(source, plugin_uri, LADSPA_BASE "hasSetting", setting_uri,
lrdf_uri);
lrdf_add_triple(source, setting_uri, RDF_BASE "type", LADSPA_BASE "Preset",
lrdf_uri);
lrdf_add_triple(source, setting_uri, LADSPA_BASE "hasLabel", label,
lrdf_literal);
for (i=0; i<vals->count; i++) {
char value_uri[64];
char port_uri[64];
char value_lit[64];
snprintf(value_uri, 64, "http://plugin.org.uk/genid#%d.%d", lrdf_uid,
sid++);
snprintf(port_uri, 64, "%s.%ld", plugin_uri, vals->items[i].pid);
snprintf(value_lit, 64, "%f", vals->items[i].value);
lrdf_add_triple(source, setting_uri, LADSPA_BASE "hasPortValue",
value_uri, lrdf_uri);
lrdf_add_triple(source, value_uri, RDF_BASE "value",
value_lit, lrdf_literal);
lrdf_add_triple(source, value_uri, LADSPA_BASE "forPort",
port_uri, lrdf_uri);
}
return setting_uri;
}
/* vi:set ts=8 sts=4 sw=4: */